2016-12-10 75 views
2

當您使用unique_ptr<T>成正向聲明的類型T,該unique_ptr析構函數需要T完成,但此舉賦值運算符,以及(和reset),根據該表:C++/pimpl:原始指針還是unique_ptr?什麼是更好的選擇?

https://stackoverflow.com/a/6089065/1794803

所以,爲您pImpl成語,要正確實現它,你必須聲明deletemove assignment method(其中,作爲副作用,標誌着他們非內聯):

class impl_t; 

class A 
{ 
    std::unique_ptr<impl_t> p_impl; 

public: 
    // Implement in A.cpp as A::~A() = default; 
    ~A(); 

    // Implemented in A.cpp as A& operator=(A&&) = default; 
    A& operator=(A&& he); 
}; 

但是,由於std::unique_ptr是動態內存的RAII解決方案,並且您已經在一個類中,並且您不得不寫一個析構函數,所以管理一個原始指針不是更好,因爲您的類是已經是RAII般從視圖的p_impl點:

class impl_t; 

class A 
{ 
    impl_t* p_impl; 

public: 
    ~A(); // The destructor must be written anyway. 

    // The omitted move assignment destructor doesn't cause UB. 
}; 

是不是一個更好的解決方案? (+如果您想要課程可以複製/移動,則定義或刪除您自己的複製/移動操作符;但這是「有意識的選擇」;但是,不要寫作unique_ptr的移動任務是錯誤的)。

使用unique_ptr只能在不得不聲明的析構函數中寫入delete p_impl

unique_ptr對於即使在例外的情況下也會被破壞的局部動態對象來說是一個很好的選擇,但對於「屬性」來說,除了獲得UB的可能性,如果你不記得你必須重寫這個移動賦值運算符。

回答

4

好,使用std::unique_ptr贖回您從明確deletep_impl困擾。

此外,它應該在構造函數中的併發訪問和異常情況下運行良好(這似乎不能保證使用原始指針和new自己)。

+0

此外,沒有定製刪除器的'std :: unique_ptr'在優化之後就可以與原始指針進行比較。 – skypjack

0

std :: unique_ptr應該是pimpl的首選方式。作爲參考,請參閱Herb Sutter's talk at CppCon16約10分鐘。 原因是,它會阻止你在保持RAII的同時意外改變你的pimpl。

相關問題