不好馴服的析構函數

不好馴服的析構函數

本文假定您對C++的面向對象機制有一些瞭解,並且對指針比較清楚。您可以隨便轉載,但是必須保證文章的完整性,並且註明出處。

很願意和您交朋友:[email protected]

注:想問我是學C還是C++的朋友就不要發郵件了,謝謝!

首先看一個深拷貝的例子

  可能我寫的有點亂,成員變量包括一個指針,其實是一個數組,想要深拷貝。

所以我們需要重載拷貝構造函數。

初學C++的時候,直接記住了參數是引用類型,當時對語言沒有深入的理解(雖然現在也不深入),也就沒有往心裏去,這些天模擬STL,遇到了好多關於深拷貝的問題,而且這問題出的很怪異(我會在下午提出),因此想到了拷貝構造函數,所以在這裏需要深究一下。

拷貝構造函數的參數是引用類型。

我們可以試想一下不是引用的情況,也就是說,拷貝構造函數是下邊這個樣子:

參數傳遞的是一個對象,按值傳遞,那麼這個對象就會被複制到right,複製的時候又會調用拷貝構造函數,那又會複製一個對象到第二次調用的這個拷貝構造函數裏邊,因此又需要第三次調用拷貝構造函數。。。想一下,是不是無限循環?

簡單地說:傳值需要調用拷貝構造函數,而不是引用類型的拷貝構造函數又需要調用拷貝構造函數。因此無限循環。

Ok,把引用的這個問題說明白,下邊說一下我這幾天遇到的這個問題:

請先看一段代碼:

可以試着運行一下,在我電腦上邊出現了下邊這個錯誤

很恐怖的錯誤。呵呵,讓我們詳細分析一下。

第一次a.show()成功,說明對象a建立沒有問題;b.show()失敗,說明沒有複製成功;第二次a.show()失敗,說明a被修改了,可以猜想一下,是不是被調用了析構函數?

現在重載 的時候是按值傳遞,那麼,我們傳進去的是地址psize

之後是執行拷貝的函數,這個沒啥問題,把right中的相關數據拷貝。

然後就開始執行析構函數了,首先析構的是傳進來的參數,也就是right,由於rightp和主函數中ap相等,因此rightpdelete了也就是apdelete了,在這裏,我們把主函數中的a不小心析構了一點點(把pdelete了)。因爲函數的返回的是值,所以第二步析構的是(*this),這樣,就把複製後的pdelete了。到這裏,我們悲劇地把內存中所有的pdelete了。

所以,當再次輸出ab的時候,全都是隨機值。

細心的朋友可能會發現,當第二次輸出ab的時候仍然是輸出了10個,也就是開始的size值。asize10不難理解。由於析構函數是在函數返回後調用的,所以返回的bsize是不改變的(返回是在改變以前)。

我們試着改一下:

下邊是我在參數上邊加了&,這樣,當再次輸出a的時候沒有錯誤

下邊是在參數right和返回值都加了&這樣就沒有錯誤了

正好符合我們的分析。
發佈了36 篇原創文章 · 獲贊 4 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章