2015-08-20 15 views
6

我正在爲一個容器寫一個drop-replacement,並且我試圖讓 得到所有異常保證。我目前正在編寫 ,clear方法,並且我希望它儘可能地完成,並且始終保持容器處於一致狀態,即使其中一個析構函數拋出異常。在我完成清潔後,我還想重新拋出 這個例外,最好不要切片。何時破壞了一個異常對象(並且可以控制它)?

這給我帶來了問題;何時破壞了一個例外? 讓我們看看一次嘗試: 這個例子簡化了。

void container::clear() 
{ 
    bool had_exception = false; 
    std::exception* exp; 
    internal_set_empty(); // this cant throw 
    while(! internal_done()) 
    { 
     try 
     { 
      internal_destruct_next(); // this might throw if T::~T() throws 
     } 
     catch(std::exception& e) 
     { 
      had_exception = true; 
      exp = &e; 
     } 
    } 
    if(had_exception) 
     throw *exp; 
} 

我希望這根本無法運行,因爲異常可能是破壞 當它被認爲是處理,而這在技術上不重新拋出。

另一個嘗試將採取異常的副本,這是 我希望將切片。

有沒有辦法延長例外的生命週期,以便我可以在以後重新拋出 ? 如果可能的話,我還希望能夠通過catch(...)重新拋出捕獲的異常 。

+0

http:// en。如果您的方案可行,cppreference.com/w/cpp/error/exception_ptr可能會很方便。 – Mat

+0

@Mat'exception_ptr'看起來像我正在尋找的東西,但它似乎有一個更基本的問題。 – sp2danny

回答

4

即使析構函數之一拋出異常

不能完成。因爲某個原因,析構函數並非如此 - 你無法從析構函數中恢復。很顯然,你沒有做任何事情去清理那些被破壞的東西 - 因爲你甚至可以試圖去做那件事 - 但是這也意味着你剛剛把他們留在了殭屍狀態。

在更具體的問題上,您可以使用遞歸來保留catch的堆棧框架以嘗試保持刪除元素,或者也可以使用std::exception_ptr和C++ 11中用於傳輸異常的朋友。

+0

謝謝。我也發現[this](http://stackoverflow.com/questions/130117/throwing-exceptions-out-of-a-destructor)很有趣 – sp2danny

1

將異常傳遞給調用者的當前用法是將其重新拋入捕獲塊中。假設你有充分的理由不這樣做,唯一的其他正確方法是使用std::exception_ptr。只有std::exception*有很高的風險,即異常被破壞,並且它的內存在釋放之前會被重新分配。

標準C++ 2011草案(n4296)表示在15.1拋出異常§4:異常或者最後剩餘活性爲異常退出通過任何方式處理程序後 對象被銷燬其他 比重新拋出,或最後引用異常對象的std :: exception_ptr類型的對象是 銷燬的,以較晚者爲準。在前一種情況下,當處理程序退出時發生破壞,在處理程序中的異常聲明中聲明的對象被銷燬後立即銷燬 ,如果有的話。在後者 的情況下,破壞發生在std :: exception_ptr返回的析構函數之前。然後,實現 可以取消分配異常對象的存儲器;任何這樣的解除分配都以未指定的方式完成 方式(強調我的)

相關問題