0

From earlier great posts (such as What are the differences between a pointer variable and a reference variable in C++?), I learned that a reference can prolong the life of a temporary object. So, I decided to try this myself and obtained a very unexpected (to me) result. Here is the code:

#include <iostream>
using namespace std;

class B {
public:
  B() {cout << "Constructor of B" << endl;}
  ~B() {cout << "Destructor of B" << endl;}
  void methodB(){cout << "B is alive!" << endl;}
};

class A {
public: 
  A() {cout << "Constructor of A" << endl;}
  ~A() {cout << "Destructor of A" << endl;}
  B &methodA() {
    cout << "Entering methodA()" << endl;
    B b;
    B &a = b;
    cout << "Exiting methodA()" << endl;
    return a;
  }
};

int main() {
  A a;
  B &b = a.methodA();
  cout << "After the call to methodA()" << endl;
  b.methodB();
  return 0;
}

I would expect that the object of class B be destroyed when main() completes. However, this is the output that I got:

Constructor of A
Entering methodA()
Constructor of B
Exiting methodA()
Destructor of B
After the call to methodA()
B is alive!
Destructor of A

Note how the call to methodB() is performed after the destructor of B had been executed. What is the explanation for this behavior?

Community
  • 1
  • 1
  • You have distinct instances of `A`'s and `B`'s in your sample. They are unrelated! – πάντα ῥεῖ May 29 '14 at 09:50
  • in methodA(), you return a reference to a local variable. Your compiler should warn you about it, don't do that. – erenon May 29 '14 at 09:51
  • You are returning a reference to a variable on the stack. The B you initialize in methodA is destructed at the end of the method. You then return a reference to it which now points to garbage data. – odyss-jii May 29 '14 at 09:52
  • the "Destructor of B" you are seeing is the local B created in methodB() being destroyed, this is expected. – quantdev May 29 '14 at 09:52
  • I do not understand what you mean. As the output witnesses, the constructor of A is called only once, same goes for constructor of B. Doesn't this mean that I have only one instance of each class? – user3593800 May 29 '14 at 09:53
  • This is the standard behavior. Return a copy of your object if you want to keep it. If your concerned with performances, this is ofter a free copy because of "copy elision optimization". – johan d May 29 '14 at 09:54
  • That is the point I started with: I understood that one can reference a temporary object and the object will be alive as long as the reference is. Where am I going wrong? – user3593800 May 29 '14 at 09:55
  • This is not a temporary object, you return a reference to a normal named variable. The fact that object is destroyed before the reference to it goes out of scope doesn't make this object temporary. – Paul May 29 '14 at 09:59

1 Answers1

1

I learned that a reference can prolong the life of a temporary object

There are no references to temporary objects in your code. You return a reference to a local variable that is destroyed after you return from A::methodA(). "B is alive!" is printed just because you don't reference any B's member variables in B::methodB(). This is invalid, but it may (or may not) work.

Calling b.methodB() is basically calling a function that has implicit hidden first argument of type B* const and value &b. In your case b object is already destroyed (you saw the destructor executed), &b points to some memory on the stack where the object was placed when it was alive, but because you don't reference any B's members this pointer is never dereferenced and this works (though you should never rely on this).

Paul
  • 13,042
  • 3
  • 41
  • 59
  • Isn't local variable a kind of temporary object? (in fact, a local variable has a larger scope: a temporary object's scope is only the expression where it appears). What is the principal difference between them? (i.e. why can't the destruction of a local variable be postponed in the same way as the destruction of a temporary object is postponed when there is a reference?) – user3593800 May 29 '14 at 10:01
  • No, local variables and temporaries are different things. Paragraph 12.2 [class.temporary] of C++ standard describes what temporaries are. – Paul May 29 '14 at 10:07