0

I am new to c++, and I read a little bit on return value optimization on wiki and also this website, however I am still curious how the following behavior happens:

using namespace std;
class A
{
    public:
        A()           {cout << "A Ctor" << endl;}
        A(const A &a) {cout << "A copy Ctor" << endl;}
};

A Foo()
{
    A a;
    return a;
}

int _tmain(int argc, _TCHAR* argv[])
{
    cout << "Foo()" << endl;
    Foo();
    cout << "Foo() and new object" << endl;
    A b(Foo());
    return 0;
}

and the output is:

Foo()
A Ctor
A copy Ctor
Foo() and new object
A Ctor
A copy Ctor

my question is, why Foo(); and A b(Foo()); both only triggered one copy constructor call? Does that mean the returned copied value from Foo() can be used to construct object b in that place so that b's constructor is not needed to be called again? This was based on visual studio 2010.

QnA
  • 1,035
  • 10
  • 25
  • `A b(Foo());` shouldn't call anything...It's a function prototype. – David G Sep 09 '13 at 20:29
  • @0x499602D2: [sure about that?](http://ideone.com/IzfGpg) – Mooing Duck Sep 09 '13 at 20:31
  • 1
    @QnA I bet you get different results in Release builds than a Debug build. – Mooing Duck Sep 09 '13 at 20:31
  • Thanks for the answering, that was quick! @MooingDuck you are correct, release build got rid of both copy ctor calls. But I'm still curious what's the logic in debug build, where both case call only one copy ctor. – QnA Sep 09 '13 at 20:35
  • I'm not sure, I don't have a good explanation as to why they both had one copy ctor. I can understand 0/1, and 1/2, and 2/2, but 1/1 baffles me. – Mooing Duck Sep 09 '13 at 20:37
  • Some compilers just do apply too many changes to the code in debug build, which are incompatible to a release build (maybe a missing RVO, having types with a different size, ...) –  Sep 09 '13 at 20:51
  • 2
    My guess. NRVO kicks in in VC++ only on `-O2` optimization level, while RVO always works. `A b(Foo());` is RVO, compiler uses `b` as a temporary. (About RVO _always_ working is my guess.) – lapk Sep 09 '13 at 20:54

1 Answers1

2

Return Value Optimization (RVO) states that a compiler can elide one or both copies, but it is not required. This means that:

A a (Foo());

Is free to do 0, 1, or 2 copy constructors:

2 - In function Foo(), A a creates an A. When it tries to return, it copies the A into the return value; the resulting initialization A a(Foo()); copies the result of Foo() into a new A.

1 - One of those copies doesn't happen (probably the copy into Foo's return value.

0 - Neither of those copies happen. The A a created inside of Foo directly becomes the A created in this line: A a(Foo());

Msdn has a lot of detail about how the visual c++ compiler handles RVO. It has some neat code examples that explain how it effectively works.

Tim
  • 8,912
  • 3
  • 39
  • 57