析構函數是類的另一個特殊成員函數,它的作用與構造函數相反,C++規定析構函數的名字是類的前面加上一個波浪號(~):
~類名()
{
函數體
}
析構函數不返回任何值,沒有返回類型,也沒有函數參數。由於沒有函數參數,因此它不能被重載。換言之,一個類可以有多個構造函數,但是只能有一個析構函數。
(一)何時調用析構函數
當對象的生命周期結束時,撤銷類對象時候會自動調用析構函數。
1)對象在生命期結束,撤銷類對象時會自動調用析構函數。
如果在一個函數中定義了一個非靜態局部對象,那當函數調用結束時候,對象被釋放,在對象被釋放前調用析構函數。
函數中的靜態局部對象在函數調用結束時候對象並不釋放,因此不調用析構函數。靜態局部對象或全局作用域的對象只有在主函數結束時候,才會調用析構函數。
2)如果用new運算動態地建立一個對象,那用delete運算符釋放該對象時,才會調用析構函數。
這種方式不以作用域范圍為對象的生命期,而是以執行new和delete運算區間為生命期,因此這種方式可以跨越多個函數作用域。需要注意,盡管動態對象可以跨作用域范圍,保存動態對象的指針變量確實以作用域范圍為聲明周期的。
動態對象的指針即使超出其作用域,也不會自動調用對象的析構函數,只有在指向該對象的指針被delete時才撤銷。如果沒有delete指向動態對象的指針,對象就一直存在,導致內存泄漏,對象內部使用的任何資源也不會釋放。
(二)合成析構函數
編譯器總是會為類生成一個析構函數,稱為合成析構函數。合成析構函數按照對象創建時的逆序來撤銷每個非靜態成員,即它是按照成員在類中聲明的次序來撤銷成員的。對於類類型的每個成員,合成析構函數調用該成員的析構函數來撤銷對象。
需要注意,合成析構函數並不刪除指針成員所指向的對象,他需要程序員顯示地編寫析構函數去處理。
(三)何時需要編寫析構函數
許多類不需要顯式編寫析構函數。析構函數通常用於釋放在構造函數或在生命期內獲得的資源(如動態分配的內存)。廣義上講,析構函數的作用並不僅僅限於釋放資源方面,它可以執行任意操作,用來執行“對象即將被撤銷之前程序員所期待的任何操作。
如果類需要析構函數,則該類幾乎必然需要定義自己的復制構造函數和賦值運算符重載,這個規則稱為析構函數三法則。原因是如果類真的需要析構函數,則類中必然出現了指針類型成員且分配了資源(否則使用合成析構函數就可以了)同時,有指針類型的成員,應該盡可能防止淺復制。所以,一定需要復制構造函數和賦值運算符重載,這兩個函數是防止淺復制所必需的。
(四)構造函數與析構函數調用次序
先構造的后析構,后構造的先析構。