析構的問題

2021-07-05 11:06:26 字數 1236 閱讀 7316

關於以下**,哪個說法是正確的?

1 2

3 4

5 6

7 8

myclass::foo()

.. void func()

正確答案: b 你的答案: c (錯誤)

a它會引起棧溢位

b都不正確

c它不能編譯

d它會引起段錯誤

在類的成員函式中能不能呼叫delete this?答案是肯定的,能呼叫,而且很多老一點的庫都有這種**。假設這個成員函式名字叫release,而delete this就在這個release方法中被呼叫,那麼這個物件在呼叫release方法後,還能進行其他操作,如呼叫該物件的其他方法麼?答案仍然是肯定 的,呼叫release之後還能呼叫其他的方法,但是有個前提:被呼叫的方法不涉及這個物件的資料成員和虛函式。說到這裡,相信大家都能明白為什麼會這樣 了。

根本原因在於delete操作符的功能和類物件的記憶體模型。當乙個類物件宣告時,系統會為其分配記憶體空間。在類物件的記憶體空間中,只有資料成員和虛函式表指標,並不包含**內容,類的成員函式單獨放在**段中。在呼叫成員函式時,隱含傳遞乙個this指標,讓成員函式知道當前是哪個物件在呼叫它。當 呼叫delete this時,類物件的記憶體空間被釋放。在delete this之後進行的其他任何函式呼叫,只要不涉及到this指標的內容,都能夠正常執行。一旦涉及到this指標,如運算元據成員,呼叫虛函式等,就會出現不可預期的問題。

為什麼是不可預期的問題?delete this之後不是釋放了類物件的記憶體空間了麼,那麼這段記憶體應該已經還給系統,不再屬於這個程序。照這個邏輯來看,應該發生指標錯誤,無訪問許可權之類的令系統崩潰的問題才對啊?這個問題牽涉到作業系統的記憶體管理策略。delete this釋放了類物件的記憶體空間,但是記憶體空間卻並不是馬上被**到系統中,可能是緩衝或者其他什麼原因,導致這段記憶體空間暫時並沒有被系統收回。此時這段記憶體是可以訪問的,你可以加上100,加上200,但是其中的值卻是不確定的。當你獲取資料成員,可能得到的是一串很長的未初始化的隨機數;訪問虛函式表,指標無效的可能性非常高,造成系統崩潰。

大致明白在成員函式中呼叫delete this會發生什麼之後,再來看看另乙個問題,如果在類的析構函式中呼叫delete this,會發生什麼?實驗告訴我們,會導致堆疊溢位。原因很簡單,delete的本質是「為將被釋放的記憶體呼叫乙個或多個析構函式,然後,釋放記憶體」 (來自effective c++)。顯然,delete this會去呼叫本物件的析構函式,而析構函式中又呼叫delete this,形成無限遞迴,造成堆疊溢位,系統崩潰。

虛析構函式與非虛析構函式問題!

class a class b public a int main 這種情況下,輸出結果我們都知道,是先執行子類的析構函式,後執行父類的析構函式,所以輸出是 b 和 a class a class b public a int main 這種情況下,我是記住了,析構函式在執行的時候,只有乙個執行,但...

關於棧的析構問題

關於棧這個問題我自己理解的比較抽象,其實我之前也寫過,在c中我們可以把棧區看成是cpu,下面我將它與作業系統的部分理論結合起來講解好了,倘若我們把每個模組 即函式 看成是就緒狀態,也就是說,我們寫出 就是已經準備執行的狀態,但是倘若我們不進行編譯的話,也就是說不給它分配記憶體空間 cpu 這樣的話,...

虛析構函式問題

虛析構函式是為了解決這樣的乙個問題 基類的 指標指向派生類物件,並用基類的指標刪除派生類物件。如果某個類不包含 虛函式,那一般是表示它將不作為乙個基類來使用。當乙個類不準備作為基類使用時,使析構函式為虛一般是個壞主意。因為它會為類增加乙個 虛函式表,使得物件的體積翻倍,還有可能降低其可移植性。所以基...