Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does returning a temporary object create a temporary object in C++?

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?

like image 471
xskxzr Avatar asked Oct 30 '15 10:10

xskxzr


People also ask

Is temporary object created in return by reference?

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.

Is the return value temporary?

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.

Where the temporary objects are created?

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.

What are temporary objects?

A temporary object is an unnamed object created by the compiler to store a temporary value.


3 Answers

(§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";
    }
};
like image 59
SingerOfTheFall Avatar answered Sep 28 '22 10:09

SingerOfTheFall


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&&
like image 40
m.s. Avatar answered Sep 28 '22 09:09

m.s.


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.

like image 23
Johan Avatar answered Sep 28 '22 10:09

Johan