在類的成員函數(shù)中調(diào)用delete this
?? 在類的成員函數(shù)中能不能調(diào)用delete this?答案是肯定的,能調(diào)用,而且很多老一點的庫都有這種代碼。假設(shè)這個成員函數(shù)名字叫release,而delete this就在這個release方法中被調(diào)用,那么這個對象在調(diào)用release方法后,還能進行其他操作,如調(diào)用該對象的其他方法么?答案仍然是肯定的,調(diào)用release之后還能調(diào)用其他的方法,但是有個前提:被調(diào)用的方法不涉及這個對象的數(shù)據(jù)成員和虛函數(shù)。說到這里,相信大家都能明白為什么會這樣了。
根本原因在于delete操作符的功能和類對象的內(nèi)存模型。當一個類對象聲明時,系統(tǒng)會為其分配內(nèi)存空間。在類對象的內(nèi)存空間中,只有數(shù)據(jù)成員和虛函數(shù)表指針,并不包含代碼內(nèi)容,類的成員函數(shù)單獨放在代碼段中。在調(diào)用成員函數(shù)時,隱含傳遞一個this指針,讓成員函數(shù)知道當前是哪個對象在調(diào)用它。當調(diào)用delete this時,類對象的內(nèi)存空間被釋放。在delete this之后進行的其他任何函數(shù)調(diào)用,只要不涉及到this指針的內(nèi)容,都能夠正常運行。一旦涉及到this指針,如操作數(shù)據(jù)成員,調(diào)用虛函數(shù)等,就會出現(xiàn)不可預(yù)期的問題。
為什么是不可預(yù)期的問題?delete this之后不是釋放了類對象的內(nèi)存空間了么,那么這段內(nèi)存應(yīng)該已經(jīng)還給系統(tǒng),不再屬于這個進程。照這個邏輯來看,應(yīng)該發(fā)生指針錯誤,無訪問權(quán)限之類的令系統(tǒng)崩潰的問題才對???這個問題牽涉到操作系統(tǒng)的內(nèi)存管理策略。delete this釋放了類對象的內(nèi)存空間,但是內(nèi)存空間卻并不是馬上被回收到系統(tǒng)中,可能是緩沖或者其他什么原因,導(dǎo)致這段內(nèi)存空間暫時并沒有被系統(tǒng)收回。此時這段內(nèi)存是可以訪問的,你可以加上100,加上200,但是其中的值卻是不確定的。當你獲取數(shù)據(jù)成員,可能得到的是一串很長的未初始化的隨機數(shù);訪問虛函數(shù)表,指針無效的可能性非常高,造成系統(tǒng)崩潰。
大致明白在成員函數(shù)中調(diào)用delete this會發(fā)生什么之后,再來看看另一個問題,如果在類的析構(gòu)函數(shù)中調(diào)用delete this,會發(fā)生什么?實驗告訴我們,會導(dǎo)致堆棧溢出。原因很簡單,delete的本質(zhì)是“為將被釋放的內(nèi)存調(diào)用一個或多個析構(gòu)函數(shù),然后,釋放內(nèi)存” (來自effective c++)。顯然,delete this會去調(diào)用本對象的析構(gòu)函數(shù),而析構(gòu)函數(shù)中又調(diào)用delete this,形成無限遞歸,造成堆棧溢出,系統(tǒng)崩潰。
--------------------我是分界面--------------------
上面是某大牛的分析,而在實際的運行過程中使用delele this確實會直接出現(xiàn)錯誤。這是因為:在成員函數(shù)中調(diào)用delete this,首先會調(diào)用類的析構(gòu)函數(shù),this指針已刪除,會出現(xiàn)指針錯誤。
下面是在XCode中使用delete this出現(xiàn)的錯誤:
malloc: *** error for object 0xbffffa18: pointer being freed was not allocated
//注意0xbffffa18即為this的地址
*** set a breakpoint in malloc_error_break to debug
而在VS2010中使用delete this是直接導(dǎo)致 Debug Assertion Failed!
具體的描述是:invalid null pointer
總結(jié):在成員函數(shù)中調(diào)用delete this,會導(dǎo)致指針錯誤,而在析構(gòu)函數(shù)中調(diào)用delete this,出導(dǎo)致死循環(huán),造成堆棧溢出。
PS:this是類中成員函數(shù)具有的一個附加的隱含形參,即指向該類對象的一個指針,它與調(diào)用成員函數(shù)的對象綁定在一起。同時1.在普通的非const成員函數(shù)中:this的類型是一個指向類類型的const指針,可以改變this指向的值,但是不能改變this所保存的地址;2.在const成員函數(shù)中,this的類型是一個指向const類類型對象的const指針,既不能改變this所指向的對象,也不能改變this所保存的地址。
注意:
成員函數(shù)中不能定義this形參,而是由編譯器隱含地定義,但是可以在成員函數(shù)中顯示使用this形參,不過也不是必須這么做。如果對類成員的引用沒有限定,編譯器會將這種引用處理成通過this指針的引用。 有一種情況下必須顯式使用this:當我們需要將一個對象作為整體引用而不是引用對象的一個成員時。 從const成員函數(shù)返回*this:不能從const成員函數(shù)返回指向類對象的普通引用。const成員函數(shù)只能返回*this作為一個const引用。