2012-06-04 41 views
4

在做我的编程任务时,我似乎在绊倒基本的C++概念。我在程序中发现了这个错误,它是由我的析构函数运行的次数超出了我的预期。这是一个代码示例,演示我做错了什么,直到最基本的东西。C++:为什么我的析构函数运行两次?

#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);堆栈名为fooA对象的空间分配和调用构造函数,传递7。它将7分配给number,并输出指示构造函数运行的输出。现在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. 

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

+3

也制作嘈杂的复制构造函数。 –

+0

查看[Rule of Three](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-ree) – rlduffy

+0

[为什么该类的析构函数被调用两次?] (HTTP://计算器。com/questions/2627540 /为什么是这个类的析构函数 - 两次) –

回答

1

显然它来自成员数据A a;我猜你的疑惑是,为什么不能从A中看到任何构造输出,因为它是用A类的默认copy-ctor构造的,最好为A类添加一个copy-ctor,以便你能看到构造程序。

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

因为在B类中,有一个成员A a 所以要破坏B对象,先调用它的成员的析构函数。

1

当人们对“foo”和“bar”感到可爱时,我讨厌它。

但我看到两个“A”的实例正在构建 - 一个显式地,另一个隐式地由“B”构造。并调用两个析构函数。

什么是不喜欢这张图片;)?

2

B构造由值取A对象,这意味着foo被复制到其中,然后被复制到成员a参数pa。编译器已经能够删除其中一个副本(构造函数的参数),但另一个不能被删除,并且你有第二个被破坏的对象。