2016-12-10 10 views
2

あなたはこの表に従ってunique_ptrデストラクタはTが完了する必要があり、前方宣言された型Tためunique_ptr<T>を使用しますが、移動代入演算子としても(とreset)、時:C++/pimpl:生ポインタまたはunique_ptr?より良い選択は何ですか?

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

ので、

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); 
}; 
:あなたの pImplイディオムのために、それを正しく実装するには、(副作用として、非インラインそれらをマークし、) deletemove assignment methodを宣言する必要が

しかし、std::unique_ptrは動的メモリ用のRAIIソリューションであり、pImplはすでにクラス内にあり、とにかくデストラクタを作成する必要があります。クラスが存在するため、生のポインタを管理するほうが良いでしょうか?すでに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を使用してp_implの明示的なdeleteで悩まからあなたを償還します。

コンストラクタで並行アクセスと例外的なケースが発生した場合でもうまく動作するはずです(生のポインタとnew自分では保証されていないようです)。

+0

また、カスタムディテッターのない 'std :: unique_ptr'は、いったん最適化されると、サイズに関して生ポインタと匹敵します。 – skypjack

0

std :: unique_ptrは、pimplの推奨方法です。参考までに、約10分でHerb Sutter's talk at CppCon16を参照してください。 理由は、RAIIを維持している間にあなたが偶然あなたのパイロットを変えるのを防ぎます。

関連する問題