> I have found somewhere else that says when an expression such as a = b + c + d.
> That when this is evaluated, c + d creates a temp object, then b + that temp creates another temp,
> and then a = that new temp.
If a, b, c, d are of a scalar type (say int), this is not correct. For instance, the value of c+d needs to be computed; the code for doing that is generated; but no temporary object is created; there is no temporary materialisation.
Temporary materialisation:
https://en.cppreference.com/w/cpp/language/implicit_conversion#Temporary_materialization
> Are temp objects created when passing to functions, if so is it the same for by value and by reference?
> Are they created when variables are being passed to all constructors?
Scott Myers in 'More Effective C++':
True temporary objects in C++ are invisible - they don't appear in your source code. They arise whenever a non-heap object is created but not named. Such unnamed objects usually arise in one of two situations: when implicit type conversions are applied to make function calls succeed and when functions return objects.
Consider first the case in which temporary objects are created to make function calls succeed. This happens when the type of object passed to a function is not the same as the type of the parameter to which it is being bound. These conversions occur only when passing objects by value or when passing to a reference-to-const parameter. They do not occur when passing an object to a reference-to-non-const parameter.
The second set of circumstances under which temporary objects are created is when a function returns an object. Anytime you see a reference-to-const parameter, the possibility exists that a temporary will be created to bind to that parameter. Anytime you see a function returning an object, a temporary will be created (and later destroyed). |
A good optimiser can exploit the as-if rule and optimise away creation of temporaries if the creation (and destruction) of these do not affect the observable behaviour of the program.
The as-if rule:
https://en.cppreference.com/w/cpp/language/as_if
For instance, several temporaries could be created for this code fragment (binding references to prvalues, member access on a class prvalue, array subscripting, discarded value expression). But the optimiser knowns what is going on and can exploit the as-if rule to avoid the creation of needless temporaries (even when the standard allows them to be created).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
struct A
{
char arr[3] {};
A( int v ) : arr{ char(v), char(v+1), char(v+2) } {}
int bar() const { return arr[1] - arr[0] ; }
};
void foo( int& n )
{
const int& n1 = n - 2 ;
const int& n2 = 1 - n ;
const int& n3 = A(7).bar() ;
n += n1 + n2 + n3 ;
}
void foo_optimised( int& ) { /* nothing */ }
|
https://gcc.godbolt.org/z/YTnhhP
I would suggest that at this stage do not worry excessively about the impact of temporaries on performance; focus on writing clean, maintainable, correct code and let the optimiser do what it does best.