Matias Cicero
Matias Cicero

Reputation: 26281

Class destructor is being called twice

I have the following program:

#include<iostream>

using namespace std;

class A {
protected:
    A() { cout << "Executing A()" << endl; }
public:
    ~A() { cout << "Executing ~A()" << endl; }
};

class B : public A {
public:
    B() { cout << "Executing B()" << endl; }
    ~B() { cout << "Executing ~B()" << endl; }
};

class C : public B {
public:
    C() { cout << "Executing C()" << endl; }
    ~C() { cout << "Executing ~C()" << endl; }
};

void someFunc() {
    A a = C();
}

int main() {
    someFunc();
    return 0;
}

which prints the following:

Print screen

Why is ~A() called twice?

Upvotes: 1

Views: 120

Answers (1)

user743382
user743382

Reputation:

The destructor for A is called twice because there are two objects that need to be destroyed. By printing something when the copy or move constructor is called you can verify this:

class A {
protected:
  A() { cout << "Executing A()" << endl; }
public:
  A(const A &) { cout << "Executing A(const A &)" << endl; }
  // with recent compilers, you could also try A(A &&)
  ~A() { cout << "Executing ~A()" << endl; }
};

Output:

Executing A()
Executing B()
Executing C()
Executing A(const A &)
Executing ~C()
Executing ~B()
Executing ~A()
Executing ~A()

Basically, A a = C(); doesn't do what you might think it does. It creates an anonymous C object, and then creates a as an A object, copying from the just-created anonymous object. It does not let a somehow point to a real C object.

A variable declared as A is always an A, never any derived type. To get something to that effect, you would need to use pointers or references.

const A &a = C();

Here, a is not an A object. This creates the same anonymous C object as before, but then makes a a reference to that anonymous object, instead of attempting to create a new A object.

Upvotes: 5

Related Questions