[英]Destructor being called
在下面的代碼中,類型B
的析構函數在案例1中調用,但在案例2中沒有,當執行從fn()
返回到main
。 我不明白這種差異,因為當使用new
創建A
時,兩者都在堆內存上。 你能解釋一下嗎?
class B {
public:
B() {
printf(" [B] COntsructor");
}
~B() {
printf(" [B] Destructor");
}
};
class A {
public:
A() {
printf(" [A] COntsructor");
}
~A() {
printf(" [A] Destructor");
}
B Query() { return b; } /// Case 1
B* Query() { return &b; } /// Case 2
B b;
};
void fn()
{
A *a = new A();
B b = a->Query(); // case 1
B* b = a->Query(); // case 2
return;
}
int _tmain(int argc, _TCHAR* argv[])
{
fn();
return 0;
}
情況1:當您按值返回b
,使用復制構造函數構造局部變量b
。 除了一個副本之外的所有副本都通過Return Value Optimization進行優化 。 局部變量b
的破壞會觸發析構函數。
情況2:當你返回&b
你返回的是指向b
的指針 ,所以不需要破壞 。
編輯: 代碼顯示被調用的析構函數沒有對構造函數的相應調用。 這是因為函數返回副本是通過復制構造函數發生的。
編輯2:@ZarShardan是正確的 - 由於返回值優化,我提到的“許多副本”可能不存在。
a
永遠不會被刪除,所以沒有它或其成員的析構函數。 a->b
將使用默認構造函數構造,因此這是您看到的構造函數調用。 B b = a->Query();
將使用復制構造函數創建,該構造函數不會打印任何內容。 fn
的末尾,本地b
將超出范圍,因此這是你的析構函數調用。 如果你的拷貝構造函數添加調試代碼,如果你擁有所有調試代碼打印的值事情可能變得更加清晰this
,如果你最終刪除a
看到那些析構函數調用為好。
我沒有看到你在第二種情況下創建一個new
的B
實例,因此A作為成員保存的指針將被A
的析構函數清理,因為B
中的構造函數從未被調用過,析構函數將不會被也調用了。
對象a永遠不會被刪除,因此既不會調用它自己的析構函數也不會調用它的成員對象析構函數。
嘗試添加
delete a;
在你的函數fn()的最后
或者更好地使用std :: unique_ptr而不是裸指針。 如果您的Query成員函數拋出異常(RAII的東西),這是更好的設計
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.