析構函數在對象的生命結束時,會自動調用,你們所熟知的智能指針就是根據析構函數的這種特性而實現的,包括Qt的內存管理機制,也都是利用了析構函數的這一機制來實現的。c++創始人Bjarne Stroustrup在創造析構函數也是出於這種目的的,可見若是析構函數用的好的話,能夠省去咱們不少工做量,你再也不須要手工調用刪除對象使用的堆內存,你只須要把要刪除的堆內存放入析構函數就好了,由於當對象離開其生命週期的時候,析構函數會自動調用,C++語言規範是這樣規定析構函數的調用的:html
Destructors are invoked implicitly (1) for a constructed object with static storage duration (3.7.1) at program termination (3.6.3), (2) for a constructed object with automatic storage duration (3.7.2) when the block in which the object is created exits (6.7), (3) for a constructed temporary object when the lifetime of the temporary object ends (12.2), (4) for a constructed object allocated by a newexpression (5.3.4), through use of a deleteexpression (5.3.5), (5) in several situations due to the handling of exceptions (15.3). A program is illformed if an object of class type or array thereof is declared and the destructor for the class is not accessible at the point of the declaration. Destructors can also be invoked explicitly.c++
大意是:express
析構函數能夠由如下五種方式隱含調用:app
(1)在靜態存儲區(也即全局對象或靜態對象,這個對象放在程序的數據區)裏面構造的對象,當程序結束時,對象的析構函數會自動調用。tcp
(2)在自動存儲區(也即局部對象,這個對象放在程序的棧裏)裏面構造的對象離開其區域時,如1個函數內聲明的對象,離開函數做用域時,對象的構造函數會自動調用。函數
(3)臨時構造的對象當離開其生命週期時,該對象的析構函數會調用,此處同(2)。this
(4)new構造的對象(即對象在堆區),經過delete刪除,析構會調用spa
(5)在try,catch處理異常的狀況下,當在try塊中對象,由於異常,進入catch分支,會在catch分支中調用構造函數.net
以上5種是經過編譯器生成的默認調用方式,固然了,還有1種就是能夠經過顯示的方式調用,也即像調用函數同樣調用析構函數debug
有了上面的介紹,接下來進入咱們的主題, delete了,卻不調用析構函數的狀況,這與上面說的C++的第(4)條規範相悖,下面我以一個簡單的示例來講明:
示例由7個文件組成,testa.cpp,testa.h, testb.cpp,testb.h,testapp.h,testapp.cpp,main.cpp
下面是輸出結果,
~CTestApp()
說明delete pTestA;後沒有調用pTestA的析構函數,當把testapp.cpp文件的//#include "testa.h"註釋取消,delete後會調用pTestA析構函數,這是去掉註釋後的輸出結果:
~CTestA()
~CTestApp()
注以上的編譯環境是ming32-make,不知道其餘的編譯環境會不會出現如此問題,這個留給你們去驗證。
下面是反彙編代碼,這是在testapp.cpp裏面加了testa.h的delete pTestA反彙編代碼:
delete pTestA;
0x0040255c <+8>: mov 0x8(%ebp),%eax
0x0040255f <+11>: mov (%eax),%ebx
0x00402561 <+13>: test %ebx,%ebx
0x00402563 <+15>: je 0x402575 <~CTestApp+33>
0x00402565 <+17>: mov %ebx,(%esp)
0x00402568 <+20>: call 0x403082 <~CTestA>
0x0040256d <+25>: mov %ebx,(%esp)
0x00402570 <+28>: call 0x40aa68 <_ZdlPv>
這是在testapp.cpp裏面沒有加testa.h的delete pTestA反彙編代碼:
delete pTestA;
0x00402550 <+8>: mov 0x8(%ebp),%eax
0x00402553 <+11>: mov (%eax),%eax
0x00402555 <+13>: mov %eax,(%esp)
0x00402558 <+16>: call 0x40aa48 <_ZdlPv>
能夠看到加了testa.h的反彙編中,調用了析構函數~CTestA, call 0x403082 <~CTestA>
http://blog.csdn.net/rabinsong/article/details/9347615