面試寶典上的vector二次析構問題

2021-06-29 05:47:48 字數 1589 閱讀 5004

今天看面試寶典chap 9 stl模板與容器時,有一道面試題講vector二次析構出錯的,看了解答還不是很明白,經過google之後終於搞清楚了,記錄如下:

面試寶典上的vector二次析構問題:

#include

using namespace std; 

class cdemo 

~cdemo() 

char *str; 

}; int main() 

書上說這段程式的錯誤是vector物件指標能夠自動析構,所以不需要呼叫delete a1, 

否則會造成兩次析構。

總結一下 

1. vector *a1 = new vector (); a1是new出來的,所以必須要手工delete.這是對a1本身而言,而與a1內儲存的資料無關。 

2. a1 -> push_back(d1); 這部操作比較複雜,因為你的vector是儲存類,而不是類指標。所以首先會在棧上建立d1的乙個拷貝d1_1,壓入棧,作為引數傳遞給push_back。然後在push_back中,建立d1_1的拷貝d1_2,d1_2是儲存在a1管理的記憶體中。然後push_back return,d1_1出棧,呼叫d1_1的析構。 

3. delete a1; a1中存有d1_2,所以會刪除d1_2,自然會呼叫d1_2的析構函式。 

4. 在main中return 0, d1被自動刪除,此時呼叫d1的析構函式。 

5. 因為class cdemo沒有拷貝建構函式,所以建立拷貝時只是簡單的把新物件中每個成員變數的值設定成與原來的物件相等。相當於執行memcpy。這時問題就來了,因為你的乙個成員是char *str; 這樣d1,d1_1,d1_2的str都是指向同乙個位址。所以只有第一次呼叫cdemo的析構函式時能執行正確,以後的都會出錯。因為乙個位址只能釋放一次。 

6. 如果你的vector改為vector *a1 = new vector (); 即儲存類指標,那麼在執行delete a1之前,還要手工去刪除vector中的每個元素。 

7. 如何驗證:在析構函式中用cout輸出字串。

按我的理解: 

**執行到delete a1的時候vector呼叫了物件的析構函式~cdemo() , 

這個時候已經把d1.str = new char[32] 給釋放掉了,由於你沒有定義拷貝建構函式實現深拷貝,當**執行完畢的時候, 

你的cdemo d1物件還會自己析構一次,又會呼叫~cdemo() 一次,這個時候就出現重複delete,所以會出錯。 

如果你定義自己的拷貝建構函式實現深拷貝 

cdemo(const cdemo &cd) 

函式在執行到a1 -> push_back(d1); 

d1的副本會在堆疊中申請另外的記憶體,而不是直接指向d1.str所指向的記憶體。這個時候你再看**的執行: 

**執行到delete a1的時候vector呼叫了物件的析構函式~cdemo() ,這個時候delete掉的是副本裡申請的記憶體(深拷貝實現)。 

當**執行完畢需要析構cdemo d1的時候,delete掉的是d1.str = new char[32]; 沒有重複delete,這樣就行了。 

所以delete a1是應該的,只是要在類裡面加乙個深拷貝的拷貝建構函式。

面試寶典上的vector析構函式

面試寶典上的vector析構函式 2009 10 09 11 00 include using namespace std class cdemo cdemo char str int main 書上說這段程式的錯誤是vector物件指標能夠自動析構,所以不需要呼叫delete a1,否則會造成兩次...

面試寶典上vector的析構筆記

題目在書p105頁 include include include using namespace std class cdemo cdemo char str intmain int argc,char ar 上面這個問題就是淺拷貝的問題 cdemo中沒有具體的拷貝建構函式時,會呼叫預設的拷貝建構...

鏈上二次求和

link 正在肝的一道黑題 首先處理那個奇怪的詢問操作。我們可以對於那個奇怪的東西進行暴力推式 ans l,r sum limits r sum limits sum limits 用字首和搞一下就是 sum limits r sum limits sum 分離一下 sum limits r m s...