2012-06-04 40 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。編譯器已經能夠刪除其中一個副本(構造函數的參數),但另一個不能被刪除,並且你有第二個被破壞的對象。