2

unique_ptr<T>前方宣言型に aを使用する場合Tunique_ptrデストラクタには is complete が必要ですが、次の表によるTと移動代入演算子 (and ) も必要です。reset

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

したがって、pImplイディオムを正しく実装するには、 thedeleteと theを宣言する必要がありますmove 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 ソリューションであり、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。エラーです)。

a のみを使用すると、とにかく宣言する必要があるデストラクタunique_ptrに書かれた a を節約できます。delete p_impl

unique_ptr例外の場合でも破棄されるローカル動的オブジェクトには優れた選択肢ですが、「属性」の場合、移動代入演算子を書き直す必要があることを覚えていなければ、UB を取得する可能性しかありません。

4

2 に答える 2

4

a を使用すると、 の明示的な処理にstd::unique_ptr煩わされる必要がなくなります。deletep_impl

また、コンストラクターでの同時アクセスと例外的なケースの場合にもうまく機能するはずです(生のポインターとnewあなた自身を使用して保証されていないようです)。

于 2016-12-10T17:42:03.003 に答える
0

std::unique_ptr は pimpl に応じた好ましい方法です。参考までに、CppCon16での約 10 分の Herb Sutter の講演を参照してください。その理由は、RAII を維持しながら誤ってニキビを変更することを防ぐためです。

于 2016-12-10T18:13:09.913 に答える