#include <iostream> class A { int x; public: A(int x):x(x){std::cout<<"A():"<<this<<'\n';} A(const A&other){std::cout<<"A(const&):"<<this<<'\n';} A(A&&other){std::cout<<"A(const&&):"<<this<<'\n';} ~A(){std::cout<<"~A():"<<this<<'\n';} }; A createObject_NRVO(int param) { std::cout<<"create Object (NRVO) "<<'\n'; A a1(1), a2(2); if(param > 10) return a1; else return a2; } A createObject_RVO(int param) { std::cout<<"create Object (RVO) "<<'\n'; if(param > 10) return A(1); else return A(2); } int main() { A a = createObject_NRVO(1); //A a2 = createObject_RVO(1); } 

Call createObject_NRVO (1) to get:

create Object (NRVO)

A (): 0x7ffd83d94ec0

A (): 0x7ffd83d94ec4

A (const &&): 0x7ffd83d94ef4

~ A (): 0x7ffd83d94ec4

~ A (): 0x7ffd83d94ec0

~ A (): 0x7ffd83d94ef4

Call createObject_RVO (1) we get:

create Object (RVO)

A (): 0x7ffdb5323d84

~ A (): 0x7ffdb5323d84

Why does RVO work and NRVO doesn't?

    1 answer 1

    The fact is that with NRVO, the compiler can omit only the copy constructor, creating an object right at the call site, and it is required to create objects for both a1 and a2 , but cannot determine in advance which of these temporary objects should be created in place of the return value .

    Simply put, in order for NRVO to work in all branches of a function, the same object must be returned. The working version will look like this:

     #include <iostream> class A { int x; public: A(){std::cout<<"A():"<<this<<'\n';} A(int x):x(x){std::cout<<"A(int):"<<this<<'\n';} A(const A&other){std::cout<<"A(const&):"<<this<<'\n';} A(A&&other){std::cout<<"A(const&&):"<<this<<'\n';} ~A(){std::cout<<"~A():"<<this<<'\n';} setX(int _x){x=_x;std::cout<<"A::setX():"<<this<<'\n';} }; A createObject_NRVO(int param) { std::cout<<"create Object (NRVO) "<<'\n'; int A a; if(param > 10) { a.setX(1); } else { a.setX(2); } return a; }