0

This Question arises from a Q&A here

I have some doubts that i think cant be asked in the followup comments there, and not too sure if i could have edited the linked question with my doubts...hence a new question.

Firstly,what i learnt from the linked question is that returning ref to local is EVIL!

Now,consider the same example from that question,a bit modified though:

#include<iostream>
#include<stdio.h>
#include<string>
using namespace std;
class A
{
    public:
        int x;
        string s;
        A(int xx,string ss):x(xx),s(ss)
    {
        cout<<"A::A()"<<x<<","<<s<<"\n";
    }
        A(const A& that)
        {
            cout<<"cpy ctr\n";
            x=that.x;
            s=that.s;
        }
        A& operator=(const A& that)
        {
            cout<<"operator=\n";
        }
        ~A()
        {
            cout<<"~A()"<<s<<"\n";
        }
};

const A& getA1()
{
    A a(1,"A1");
    cout<<"returning from A1\n";
    return a;
}

A& getA2()
{
    A a(2,"A2");
    cout<<"returning from A2\n";
    return a;
}

A getA3()
{
    A a(3,"A3");
    cout<<"returning from A3\n";
    return a;
}

int main()
{ 
    A &newA2 = getA2();       //.....................LINE 2
    cout<<"returned from A2\n";
    cout<<"-----------------------------\n";
    A newA3 = getA3();       //......................LINE 3
    //A const  newConstA3 = getA3 ();
    cout<<"returned from A3\n";
    cout<<"-----------------------------\n";
    //cout<<"newA2="<<newA2.x<<","<<newA2.s<<"\n";
    cout<<"newA3="<<newA3.x<<","<<newA3.s<<"\n";

}

The output is as follows..

A::A()2,A2
returning from A2
~A()A2
returned from A2
-----------------------------
A::A()3,A3
returning from A3
returned from A3
-----------------------------
newA3=3,A3
~A()A3

Now my doubts...

  1. in LINE 2, the fun getA2() (which returns by ref) returns after destructing the temporary,so the recieving object newA2 is dangerous to use.(the reason why i have comented out its use.) so then why doesent the fun getA3() destruct the temporary even though it returns by "copy" (Note that the temporary's destructor inside getA3() doesnt get called ever..only newA3 object's destructor gets called when it dies at the end of main() )? I have no clue where does that temp go??

  2. Now if in LINE 2 i change it from A& newA2 = getA2(); to A newA2 = getA2(); ,the copy ctr gets called here(which eventually gives a segfault as the referent has died),but why doesnt the copy ctr gets called at LINE 3 ? How does the state of the temporary is getting copied into object newA3,notice no operator=() is being called either ?

  3. Lastly.. the output here is from gcc, but does MSVC++2008 work differently?? As even for the code A newA3 = getA3(); in LINE 3 it behaves the same as LINE 2,i.e, it destructs the temp before returning! any clues?

Community
  • 1
  • 1
ashishsony
  • 2,537
  • 3
  • 26
  • 38

2 Answers2

2
  1. It appears you are benefiting from Return Value Optimisation.

  2. Because you are copying an, albeit invalid, reference into a new object.

  3. MSVC and GCC work broadly the same. Avoid undefined behaviour (This can be harder than it may seem) and if they don't work the same way then there is a bug in the compiler.

Goz
  • 61,365
  • 24
  • 124
  • 204
0
  1. Well, of course the value to be returned is not destroyed, otherwise you'd never be able to return anything from a function. I believe it goes straight onto the calling scope's stack after copying it from the local scope.

  2. Copy elision. When a copy is excessive (as it would be here), the compiler is allowed to elide it (even if it has side effects) as a sort of standard-prescribed "optimisation". This is documented in many, many questions on SO.

  3. It's not clear what you're asking. You haven't shown two pieces of output to compare.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 1
    –1 because it’s wrong, in particular 1. Local variables cease existence at the end of scope, and are destroyed. You are *still* able to return values from a function because the value gets copied (before being destroyed, of course). Copy elision is a different matter entirely (the compiler is allowed this optimisation but it’s only that – an *optimisation* which doesn’t form an argument about semantics) – Who the hell upvoted this? – Konrad Rudolph Jan 26 '12 at 10:50
  • @Konrad: Er, what? 1) The value to be returned is not the local variable. It is a copy. I never said otherwise. Quite _obviously_, the value to be returned cannot be destroyed with the local scope... 2) Right, and I said that. That doesn't mean it doesn't affect the output of the program. Can you clarify on your problems with this answer? – Lightness Races in Orbit Jan 26 '12 at 11:11