Why does the destructor run twice in C++?

天大地大妈咪最大 提交于 2019-12-31 00:57:30

问题


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?


回答1:


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";
}



回答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.




回答3:


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




回答4:


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



来源:https://stackoverflow.com/questions/10875381/why-does-the-destructor-run-twice-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!