建構函式和析構函式中的異常
2008-11-29 21:39
建構函式中的異常
在建構函式中丟擲異常將中止物件的構造,這將產生乙個沒有被完整構造的物件。 對於c++來說,這種不完整的物件將被視為尚未完成建立動作而不被認可,也意味著其析構函式永遠不會被呼叫。這個行為本身無可非議,就好像公安局不會為乙個被流產的嬰兒發戶口然後再開個死亡證明書一樣。但有時也會產生一些問題,例如:
class csample
; csample::csample
()
csample::~
csample
() // 析構函式不會被呼叫
解決這個問題的方法是在丟擲異常以前釋放任何已被申請的資源。一種更好的方法是使用「資源申請即初始化」的型別(如:控制代碼類、靈巧指標類等等)來代替一般的資源申請與釋放方式,如:
templete
<
class t
>
struct cautoarray; ~
cautoarray()
t* operator
=(in t*
rhs)
// ...t*
m_p;
}; class csample
;csample::csample
() 注意:上述cautoarray類僅用於示範,對於所有權語義的通用自動指標,應該使用c++標準庫中的 "auto_ptr" 模板類。對於支援引用計數和自定義銷毀策略的通用控制代碼類,可以使用白楊工具庫中的 "chandle" 模板類。
析構函式中的異常
析構函式中的異常可能在2種情況下被丟擲:
物件被正常析構時
在乙個異常被丟擲後的退棧過程中——異常處理機制退出乙個作用域,其中所有物件的析構函式都將被呼叫。
由於c++不支援異常的異常,上述第二種情況將導致乙個致命錯誤,並使程式中止執行。例如:
class csample
;csample::
~csample
()
void
function(
void
)
如果必須要在析構函式中丟擲異常,則應該在異常丟擲前用 "std::uncaught_exception()" 事先判斷當前是否存在已被丟擲但尚未捕獲的異常。例如:
class csample
;csample::
~csample
()
} void
function(
void
)
異常的組織
異常型別應該以繼承的方式組織成乙個層次結構,這將使以不同粒度分類處理錯誤成為可能。 通常,某個軟體生產組織的所有異常都從乙個公共的基類派生出來。而每個類的異常則從該類所屬模組的公共異常基類中派生。
異常捕獲和重新丟擲
例如:try
// 公鑰加密錯誤
catch
(const cpubkeycipher
::exp
& err)
else
} //
處理其它加密庫錯誤
catch
(const
cryptoexp
& err)
// 處理其它本公司模組丟擲的錯誤
catch
(const
companyexp
& err
) // 處理 dynamic_cast 錯誤
catch
(const
bad_cast
& err
) // 處理其它標準庫錯誤
catch
(const
exception
& err
) // 處理所有其它錯誤
catch
(...)
異常和效率
對於絕大部分現代編譯器來說,在不丟擲異常的情況下,異常處理的實現在執行時不會有任何額外開銷,也就是說:正常情況下,異常機制比傳統的通過返回值判斷錯誤的開銷還來得 稍微小些。 相對於函式返回和呼叫的開銷來講,異常丟擲和捕獲的開銷通常會大一些。不過錯誤處理**通常不會頻繁呼叫,所以錯誤處理時開銷稍大一點基本上不是什麼問題。這也是我們提倡僅將異常用於錯誤處理的原因之一。
建構函式和析構函式中丟擲異常
不會造成記憶體洩漏 1 new乙個物件有兩個過程 a.向系統申請記憶體空間 b.在申請的記憶體空間上執行建構函式,初始化物件。2 內部物件構造先於物件本身。3 物件在建構函式丟擲異常後,系統會負責清理構造物件時申請的記憶體,但不會呼叫物件析構函式。也就是說構造物件的記憶體會被釋放掉,已經完成例項化的...
c 建構函式和析構函式中的異常
情況一 建構函式中有異常丟擲 建構函式中有異常丟擲,需要注意如果該建構函式中已在堆中生成了物件,要在建構函式中進行異常處理去釋放堆中資源或者使用智慧型指標,因為這時建構函式未執行成功,物件還未建立成功,在棧回退時不會呼叫析構函式,進而造成記憶體洩漏 若在堆中生成的物件則無需擔心,因為在棧回退時會釋放...
C 中建構函式和析構函式丟擲異常問題
一.丟擲異常 1.1 丟擲異常 也稱為拋棄異常 即檢測是否產生異常,在c 中,其採用throw語句來實現,如果檢測到產生異常,則丟擲異常。該語句的格式為 throw 表示式 如果在try語句塊的程式段中 包括在其中呼叫的函式 發現了異常,且拋棄了該異常,則這個異常就可以被try語句塊後的某個catc...