4

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?

jww
  • 97,681
  • 90
  • 411
  • 885
newprogrammer
  • 2,514
  • 2
  • 28
  • 46

4 Answers4

3

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.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
2

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";
}
JsDoITao
  • 114
  • 4
1

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 ;)?

paulsm4
  • 114,292
  • 17
  • 138
  • 190
0

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

RolandXu
  • 3,566
  • 2
  • 17
  • 23