面試寶典上的vector析構函式
2009-10-09 11:00
#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的析構筆記
題目在書p105頁 include include include using namespace std class cdemo cdemo char str intmain int argc,char ar 上面這個問題就是淺拷貝的問題 cdemo中沒有具體的拷貝建構函式時,會呼叫預設的拷貝建構...
面試寶典上的vector二次析構問題
今天看面試寶典chap 9 stl模板與容器時,有一道面試題講vector二次析構出錯的,看了解答還不是很明白,經過google之後終於搞清楚了,記錄如下 面試寶典上的vector二次析構問題 include using namespace std class cdemo cdemo char st...
public 函式 C 的this函式和析構函式
你可以因為現任不好而分手,但千萬不要認為別人更好,永遠有人更好,眼下便是更好。網易雲熱評 一 this函式 對於普通的成員函式,this指向呼叫該函式的物件 對於建構函式,this指向正在建立的物件 include using namespace std class teacher 通過this區分...