4

What is the fastest way to uncover where temporaries are created in my C++ code?

The answer is not always easily deducible from the standard and compiler optimizations can further eliminate temporaries.

I have experimented with godbolt.org and its fantastic. Unfortunately it often hides the trees behind the wood of assembler when it comes to temporaries. Additionally, aggressive compiler optimization options make the assembler totally unreadable.

Any other means to accomplish this?

Patrick Fromberg
  • 1,313
  • 11
  • 37

2 Answers2

4

"compiler optimizations can further eliminate temporaries."

It seems you have a slight misunderstanding of the C++ semantics. The C++ Standard talks about temporaries to define the formal semantics of a program. This is a compact way to describe a large set of possible executions.

An actual compiler doesn't need to behave at all like this. And often, they won't. Real compilers know about registers, real compilers don't pretend that POD's have (trivial) constructors and destructors. This happens already before optimizations. I don't know of any compiler that will generate trivial ctors in debug mode.

Now some semantics described by the Standard can only be achieved by a fairly close approximation. When destructors have visible side effects (think std::cout), temporaries of those types cannot be entirely eliminated. But real compilers might implement the visible side effect while not allocating any storage. The notion of a temporary existing or not existing is a binary view, and in reality there are intermediate forms.

MSalters
  • 173,980
  • 10
  • 155
  • 350
2

Due to the "as-if" rule it is probably unreliable to try to view the compilation process to see where temporaries are created.

But reading the code (and coding) while keeping in mind the following paragraph of the standard may help in finding where temporaries are created or not, [class.temporary]/2

The materialization of a temporary object is generally delayed as long as possible in order to avoid creating unnecessary temporary objects. [ Note: Temporary objects are materialized:

  • when binding a reference to a prvalue ([dcl.init.ref], [expr.type.conv], [expr.dynamic.cast], [expr.static.cast], [expr.const.cast], [expr.cast]),

  • when performing member access on a class prvalue ([expr.ref], [expr.mptr.oper]),

  • when performing an array-to-pointer conversion or subscripting on an array prvalue,

  • when initializing an object of type std​::​initializer_­list from a braced-init-list ([dcl.init.list]),

  • for certain unevaluated operands ([expr.typeid], [expr.sizeof]), and

  • when a prvalue appears as a discarded-value expression.

In this paragraph coming from the C++17 standard, the term prvalue has a new definition [basic.lval]/1:

A prvalue is an expression whose evaluation initializes an object or a bit-field, or computes the value of the operand of an operator, as specified by the context in which it appears.

And in the last standard (pre C++20), the paragraph [basic.lval] has been moved to Expressions [expr], so what we knew as value categories is evolving to become expression categories.

Oliv
  • 17,610
  • 1
  • 29
  • 72