为什么析构函数在C ++运行两次?(Why does the destructor run twic

2019-06-25 04:01发布

虽然这样做我的编程作业,我似乎被绊倒基本C ++概念。 我发现在我的程序的bug,它是由运行更多的时间比我预期的析构函数引起的。 下面是一个代码示例演示什么,我做错了,到最基本的要素。

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

我希望发生的是A foo(7); 分配堆栈空间上为A命名对象foo和调用构造,传递7 。 它分配7number和打印输出指示的构造运行。 现在B bar(foo); 堆栈对于上分配空间B对象命名bar和调用构造,传递foo由值,这仅仅是用于一个容器int 。 构造函数分配A传递给它的参数,以它自己的私有数据成员a ,并打印输出到屏幕上。

现在,当bar超出在右大括号范围,我希望bar被称为的析构函数,它打印输出到屏幕上,然后调用它的数据成员,即析构函数A a 。 即输出到屏幕上的析构函数印刷品,并丢弃int number据含有。

我期望输出应该是:

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?

实际的输出:

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

是什么原因造成额外的破坏?

Answer 1:

显然它来自部件的数据A中; B类的我猜你的疑问是,为什么不请参阅从任何构造的输出,因为它默认拷贝构造函数构造类A,这是更好地增加一个拷贝构造函数为A级,这样你会看到构建程序。

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


Answer 2:

您的B构造函数采用A由值对象,这意味着foo被复制到参数pa ,然后被复制到成员a 。 编译器已经能够在的Elid副本之一(参数构造函数),但另一个不能被省略,并有你有第二A是获得真实销毁的对象。



Answer 3:

我讨厌别人装可爱与“富”与“酒吧”。

但是,我看到正在建设中的“A”的两个实例 - 一个明确的,其他的隐式由“B”。 和两个析构函数调用得到。

有什么理由不喜欢这幅画;)?



Answer 4:

因为在B类中,具有一个部件A a ,以便于自毁B对象,第一至调用它的构件的析构函数。



文章来源: Why does the destructor run twice in C++?