考慮其中函數foo(MyClass的* MC)被認爲保留MC的拷貝到內部數據結構的情況下的功能時,解決可能的內存泄漏,並確保該對象將被刪除當不再使用時。傳遞一個目的是拋出
void foo(MyClass* mc) // acquires ownership of mc; may throw
{
// code that may throw
bar(mc); // acquires mc; may also throw
}
問題出現時,這個函數執行的代碼可能拋出(例如,內存溢出除外)。如果在將指針保存到數據結構之前引發異常,那麼在函數展開之前顯然應該釋放該對象,因爲調用者沒有更多的責任(調用者甚至不知道指針是否實際上保存在數據結構與否)。
人們可以使用RAII與範圍警衛處理這個問題,但似乎很笨拙,併產生一些開銷(它在獲取指針的每一個函數來完成)。
會怎麼需要做到這一點每一個動態分配的對象被收購的時候,或者是有一個更合適的方法來做到這一點?
template <class T>
struct VerifyAcq {
T* ptr;
bool done;
VerifyAcq(T* ptr):ptr(ptr) { done = false; }
~VerifyAcq() {
if (!done) delete ptr;
}
};
void foo(MyClass* mc) // acquires mc; may throw
{
VerifyAcq<MyClass> va(mc);
// code that may throw
bar(mc); // acquires mc; may throw; must implement the same mechanism!
va.done = true;
}
// Note: there might be no public way of "undoing" what bar has done (no rollbak)
// and even if there was, what if it could also throw?...
異常不能被調用者才能刪除指針,因爲拋出異常之前,該功能可能已經成功加入的指針數據結構,並在釋放對象將使數據結構抓不健全的(晃來晃去的指針)。
「併產生一些開銷」替代方法是不產生「開銷」並泄漏,不是?當你付出的代價是實現目標所需的成本時,沒有「開銷」。問題:你是否控制這些功能,即,你能修復它們的接口嗎? –
另一種方法是用一個全捕捉的catch塊做一個函數級try塊...這是沒有太大的替代,恕我直言 – StoryTeller