拋出異常時,將暫停當前函數的執行,開始查找匹配的catch子句。首先檢查throw本身是否在try塊內部,如果是,檢查與該try相關的catch子句,看是否可以處理該異常。如果不能處理,就退出當前函數,並且釋放當前函數的內存並銷毀局部對象,繼續到上層的調用函數中查找,直到找到一個可以處理該異常的catch。這個過程稱為棧展開(stack unwinding)。當處理該異常的catch結束之後,緊接著該catch之後的點繼續執行。
1. 為局部對象調用析構函數
如上所述,在棧展開的過程中,會釋放局部對象所占用的內存並運行類類型局部對象的析構函數。但需要注意的是,如果一個塊通過new動態分配內存,並且在釋放該資源之前發生異常,該塊因異常而退出,那麼在棧展開期間不會釋放該資源,編譯器不會刪除該指針,這樣就會造成內存洩露。
2. 析構函數應該從不拋出異常
在為某個異常進行棧展開的時候,析構函數如果又拋出自己的未經處理的另一個異常,將會導致調用標准庫terminate函數。通常terminate函數將調用abort函數,導致程序的非正常退出。所以析構函數應該從不拋出異常。
3. 異常與構造函數
如果在構造函數對象時發生異常,此時該對象可能只是被部分構造,要保證能夠適當的撤銷這些已構造的成員。
4. 未捕獲的異常將會終止程序
不能不處理異常。如果找不到匹配的catch,程序就會調用庫函數terminate。