简体   繁体   中英

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?

(§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.

The actual result in this particular case will depend on a particular compiler and optimization levels. In fact, a decent modern compiler with a good optimization level can completely remove any temporary object. Consider this:

#include <iostream>

using namespace std;

struct A {
    A(int) { cout << __PRETTY_FUNCTION__ << endl; }
    ~A() { cout << __PRETTY_FUNCTION__ << endl; }
};

inline
A foo() {
    return static_cast<A>(0);
};


int main(void) {
    A a = foo();
    cout << "hello world!" << endl;
}

gcc-5.1.1 with -O4 builds an executable which outputs literally this:

A::A(int)
hello world!
A::~A()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM