2013-07-05 76 views
3

使用unique_ptr安全嗎? 當我在析構函數中使用cout時,它有時會調用多次。 - 所以它會複製時間。如果它從一個對象中獲取兩個副本 - 數據可能會丟失。在異常類中使用unique_ptr安全嗎

#include <memory> 

class MyException 
{ 
    std::unique_ptr<Type> data; 

    MyException(); 
    ~MyException() {cout<<"test"<<endl;} 

    MyException(MyException ex&); 
}; 

int main() 
{ 
    try 
    { 
     try 
     { 
      throw MyException(); 
     } 
     catch (const MyException& ex) 
     { 
      throw; 
      //or? 
      throw ex; //will be copied? 
     } 
    return 0; 
    } 
    catch(const MyException/*& will be missed. will ex be copied?*/ ex) 
    { 
     throw; //wich ex will be re-throw, copy or original? 
     //or? 
     throw ex; //will be copied? 
    } 
} 

我可以肯定,重新引發之間的數據不會丟失嗎? 這是很好的實踐,使用異常內的ptr來收集來自不同級別的錯誤信息?

而且,可以MyException.data丟失後:

std::exception_ptr ex = std::current_exception(); 
std::rethrow_exception(ex); 
+1

重見不作副本;這是有保證的。但是,可能還有其他方面未指定是否製作副本。 「扔」; –

+0

vs 2012. - 輸出中有1個「測試」。用「throw ex;」與 - 輸出中有2個「測試」。 2析構函數= 2對象... =>複製完成。 – Darida

回答

1

當你發現,你應該總是說throw;當你要重新拋出異常,而不是不throw ex;。事實上,throw ex;將複製(和切片,如果ex是對基類的引用!)。

因此,總是通過引用來捕獲,並且總是重新拋出而沒有命名異常。

0

使用gcc 4.7.3你的例子沒有編譯,抱怨MyException缺少拷貝構造函數。這是它第一次拋出的行,所以throw MyException()本身已經想要複製(至少在gcc中)。另請參閱this stackoverflow questionC++ FAQ

要回答關於在異常中使用指針是否是良好實踐的問題,我通常會說不。除非要將數據捎帶到異常上(這可能是設計問題),否則應該首選堆棧分配的數據結構。無論如何,性能不應該成爲異常處理的主要關注點,因此複製東西並不是一個真正的問題。

如果你真的需要一個指針(也許Type沒有拷貝構造函數,但你不能改變它),使用shared_ptr可以幫助你一個捏,雖然我覺得這將是一個醜陋的黑客。我可能會嘗試將通過異常傳遞的信息減少到最低程度,以幫助呼叫者識別和處理問題。

編輯:我發現在C++ standard的相關章節,第15.1節,第5段:

當拋出的對象是類對象,複製/移動構造函數和析構函數必須是可訪問的,即使複製/移動操作被取消。

所以它實際上不合法的C++拋出一個沒有複製構造函數的異常對象。

+0

作爲一個例子,我使用'shared_ptr'來傳遞各種副本之間異常的調用堆棧。 –