user3593800
user3593800

Reputation: 11

Destructor is called while there is still a reference

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?

Upvotes: 0

Views: 243

Answers (1)

Paul
Paul

Reputation: 13238

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).

Upvotes: 1

Related Questions