構造函數和析構函數分别管理對象的建立和釋放,負責對象的誕生和死亡的過程。當一個對象誕生時,構造函數負責建立并初始化對象的内部環境,包括配置設定記憶體、建立内部對象和打開相關的外部資源,等等。而當對象死亡時,析構函數負責關閉資源、釋放内部的對象和已配置設定的記憶體。
在對象生死攸關的地方,如果程式代碼出現問題,常常會發生記憶體洩漏,進而産生可能危害系統運作的孤魂野鬼。大量的事實表明,業務邏輯代碼寫得非常嚴謹的程式在運作中仍然發現存在記憶體洩露,大都是構造和析構部分的代碼存在問題。
而許多程式員都習慣于面向對象的程式設計,需要時就建立一個對象,不用時就将其釋放。這樣的習慣簡化了我們的思路,正是面向對象程式設計思想帶來的好處。也許由于太習慣了,很多程式員都忽略了在對象生死的瞬間也可能産生異常的問題,這種現象卻值得我們去認真反思。
其實,對象生死間的異常問題是一個充滿争議的問題。甚至不同的程式設計語言,在對象生死間的異常問題上也持不同的态度。
C++語言說:一個對象在出生的過程中發生異常問題,那這個對象就是一個沒有生命的怪胎。既然它不是一個完整的對象,就根本不存在析構或釋放的說法。是以,C++在執行構造函數過程中産生異常時,是不會調用對象的析構函數的,而僅僅清理和釋放産生異常前的那些C++管理的變量空間等,之後就把異常抛給程式員處理。
那麼關于析構函數中的異常又會怎樣呢?
對象在死亡的過程中發生異常又引出一個有趣的問題,“想死死不了”或者“死了一半又不能死了”!那麼,這個對象到底是死了還是活着?這種既死又活的對象,就像量子理論中的那隻“薛定谔的貓”一樣有趣。的确存在,卻難以琢磨!
為此,C++根本不去糾纏這種複雜的問題,而是采用最簡單的辦法:如果析構函數抛出異常,将直接導緻目前執行線程異常終止!如果是主線程中發生析構異常,程式立即退出!
C++的這一做法是可以了解的,當代碼已經走進無法想通的死胡同,對象隻能瘋掉,進而毀滅整個程式世界!看來并非芸芸衆生才有無法逃脫的苦海,其實運作中的程式程序也有解不開的心結!
是以,“永遠不要在析構函數中抛出異常”成了編寫C++代碼的一條鐵律!
構造函數和析構函數中的異常
1、構造函數可以抛出異常。
2、c++标準指明析構函數不能、也不應該抛出異常。
more effective c++關于第2點提出兩點理由:
1)如果析構函數抛出異常,則異常點之後的程式不會執行,如果析構函數在異常點之後執行了某些必要的動作比如釋放某些資源,則這些動作不會執行,會造成諸如資源洩漏的問題。
2)通常異常發生時,c++的機制會調用已經構造對象的析構函數來釋放資源,此時若析構函數本身也抛出異常,則前一個異常尚未處理,又有新的異常,會造成程式崩潰的問題。
解決辦法:
1)永遠不要在析構函數抛出異常。
2)通常第一點有時候不能保證。可以采取如下的方法:
~ClassName()
{
try{
do_something();
}
catch( ){ // 這裡可以什麼都不做,隻是保證catch塊的程式抛出的異常不會被扔出析構函數之外。
}
}
小結
構造函數抛出異常後不會調用析構函數
析構函數中抛出異常時概括性總結
(1) C++中析構函數的履行不應當抛出異常;
(2) 假如析構函數中抛出了異常,那麼你的體系将變得非常危險,也許很長時光什麼錯誤也不會産生;但也許你的體系有時就會莫名奇妙地崩潰而退出了,而且什麼迹象也沒有,崩得你滿地找牙也很難發明問題畢竟呈現在什麼處所;
(3) 當在某一個析構函數中會有一些可能産生異常時,那麼就必須要把這種可能産生的異常完全封裝在析構函數内部,決不能讓它抛出函數之外;
(4) 必定要切記上面這幾條總結,析構函數中抛出異常導緻程式不明原因的崩潰是許多體系的緻命内傷!
強烈建議參閱以下連結
http://www.sunistudio.com/cppfaq/exceptions.html
http://blog.csdn.net/leadzen/article/details/1783116#
http://blog.csdn.net/jifengszf/article/details/1957667
http://baiy.cn/doc/cpp/inside_exception.htm
http://dev.yesky.com/122/2600622.shtml
http://www.builder.com.cn/2007/1027/585451.shtml
http://www.vckbase.com/document/viewdoc/?id=937
http://ticktick.blog.51cto.com/823160/191881
http://www.iteedu.com/plang/ccpp/cppdxjch2b/106.php
http://blog.csdn.net/wallwind/article/details/6765167#