Consider the following code in C++:
struct A {A(int);};
A foo() {return static_cast<A>(0);}
A x = foo();
Here static_cast<A>(0)
creates a temporary object by the standard [5.2.9-4], which is a prvalue. The standard [12.2-1] says
Temporaries of class type are created in various contexts: binding a reference to a prvalue (8.5.3), returning a prvalue (6.6.3), a conversion that creates a prvalue (4.1, 5.2.9, 5.2.11, 5.4), throwing an exception (15.1), entering a handler (15.3), and in some initializations (8.5).
So does the return statement will creates a temporary object again?
By the way, can anyone please tell me whether the standard guarantees an implicit type conversion will create an temporary object?
Explanation: The temporary object is not created. If object is returned by reference, a particular memory location will be denoted with another name and hence same address values will be used. 10.
Formally: the return value is always a temporary. In contexts where that temporary is used as the argument of a copy constructor (the object is copied), the standard gives explicit authorization for the compiler to elide the copy, “merging” the temporary with the named variable it is initializing.
Temporary objects are created by the optimizer in order to process a query. In general, these temporary objects are internal objects and cannot be accessed by a user.
A temporary object is an unnamed object created by the compiler to store a temporary value.
(§4/6) mentions that
The effect of any implicit conversion is the same as performing the corresponding declaration and initialization and then using the temporary variable as the result of the conversion.
So yes, unless optimized, a temporary should be created, but I'm sure all modern compilers will perform a copy elision in your case. This particular optimization is called return value optimization (RVO). You can easilly test it by having constructors with side effects:
struct A {
A(int){
std::cout << "ctor";
}
A(const A & other)
{
std::cout << "copy ctor";
}
A(A&&other)
{
std::cout << "move ctor";
}
};
The temporary object will (most likely) be optimized away through Return-Value-Optimization (RVO) .
Example:
#include <iostream>
struct A
{
A(int)
{
std::cout<< "A" << std::endl;
}
A(const A&)
{
std::cout << "A&" << std::endl;
}
A(A&&)
{
std::cout << "A&&" << std::endl;
}
};
A foo() {return static_cast<A>(0);}
int main()
{
A x = foo();
return 0;
}
output: live example
A
output with RVO disabled: live example
A
A&&
A&&
Short answer: No there will be only one creation of A
in your code.
To achieve this, the compiler uses the (Named) Return value optimization that eliminates unnecessary object creation/copy upon returns. The more general case, Copy elision, that eliminates unnecessary copying of objects, will be use in plenty of related case.
You can play with GCC
option -fno-elide-constructors
to see the differences.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With