newprogrammer
newprogrammer

Reputation: 2604

Why does the destructor run twice in C++?

While doing my programming assignments, I seem to be stumbling over basic C++ concepts. I found the bug in my program and it was caused by my destructor running more times than I expected. Here is a code sample demonstrating what I am doing wrong, down to the bare essentials.

#include <iostream>
using namespace std;

class A
{
public:
    A(int num)
    {
        number = num;
        cout << "A constructed with number " << number << ".\n";
    }
    ~A()
    {
        cout << "A destructed with number " << number << ".\n";
    }
private:
    int number;
};

class B
{
public:
    B(A pa)
        : a(pa)
    {
        cout << "B constructor run.\n";
    }
    ~B()
    {
        cout << "B destructor run.\n";
    }
private:
    A a;
};


int main()
{
    A foo(7);
    {
        B bar(foo);
    }
    //Pause the program.
    system("pause");
}

What I expect to happen is A foo(7); allocates space on the stack for an A object named foo and call the constructor, passing 7. It assigns 7 to number and prints output indicating the the constructor ran. Now B bar(foo); allocates space on the stack for a B object named bar and calls the constructor, passing foo by value, which is just a container for an int. The constructor assigns the A parameter passed to it to it's own private data member a, and prints output to the screen.

Now, when bar goes out of scope at the closing curly brace, I expect bar's destructor to be called, which prints output to the screen, then calls the destructor for its data members, namely A a. That destructor prints output to the screen, and discards the int number that it was containing.

What I expect the output should be:

A constructed with number 7.
B constructor run.
B destructor run.
A destructed with number 7.
//Destructors should be called in the reverse order of their construction right?

The actual output:

A constructed with number 7.
B constructor run.
A destructed with number 7. //This is unexpected.
B destructor run.
A destructed with number 7.

What is causing that extra destruction?

Upvotes: 4

Views: 1127

Answers (4)

JsDoITao
JsDoITao

Reputation: 114

Obviously it comes from member data A a; of class B. I guess your doubt is that why not see any construct output from A, because it's constructed with default copy-ctor for class A, It's better to add one copy-ctor for class A, so that you will see the construct procedure.

A(const A& a)
{
     number = a.number;
     cout << "A copy-constructed with number " << number << ".\n";
}

Upvotes: 2

Your B constructor takes the A object by value, which means that foo is copied into the parameter pa which then gets copied to the member a. The compiler has been able to elide one of the copies (argument to the constructor), but the other one cannot be elided and there you have the second A object that get's destroyed.

Upvotes: 3

paulsm4
paulsm4

Reputation: 121599

I hate it when people get cute with "foo" and "bar".

But I see two instances of "A" being constructed - one explicitly, the other implicitly by "B". And two destructors getting invoked.

What's not to like about this picture ;)?

Upvotes: 1

RolandXu
RolandXu

Reputation: 3678

because in class B, there has one member A a so to destruct B object, first to call its member's destructor.

Upvotes: 0

Related Questions