質問

私は通常、PIMPLのBoost :: Scoped_ptrを使用します(1つの理由で、コピーコンストラクターに対処するのを忘れても驚きがないので)

ただし、テンプレートを使用すると、SCOPED_PTRのデストラクタの要件を満たすために、IMPLが完全に定義されているCPPファイルにデストラクタを配置することはできません。とにかく動作しますが、仕事に取り組んでいるのか、それとも偶然にもかまいません。 「ベストプラクティス」または標準はありますか? SCOPED_PTRは、非調整不可能なクラスでPIMPLに最適なスマートポインターですか?

template <class T> class C {
public:
    C(){}
    ~C(){}
private:
    boost::scoped_ptr<T> pimpl_;
};
役に立ちましたか?

解決

boost::shared_ptr PIMPLの場合、インスタンス化の時点以外の完全な定義は必要ありません。コンストラクターの場合。 boost::shared_ptrいいえ ただし、PIMPL Idiomに適しています。これは、非常に予期しないセマンティクスを提供するためです(割り当てまたはコピーの参照セマンティクス)。スマートポインターの複雑さを追加したい場合は、 boost::scoped_ptr より多くのアプリケートになります(ただし、デストラクタがインスタンス化されている時点では、完全な定義が必要です)。

テンプレートに関しては、ヘッダーからの実装の詳細にPIMPL IDIOMを使用することは意味がありません。の不在で export、クラステンプレートの実装詳細はすべて、テンプレートが使用される至る所に含まれている必要があるため、PIMPL Idiomの背後にある動機が存在しなくなります。

他のヒント

ハーブ・サッターが長い間彼のゴットを再び書き始めたのはちょうど起こりました。最初の新しいものの1つは、「コンピレーションファイアウォール」に関連しています。

あなたは次のことを見てみることをお勧めします:

GOTW#100:コンピレーションファイアウォール(難易度:6/10)

GOTW#101:コンピレーションファイアウォール、パート2(難易度:8/10)

2年後、私は状況をはるかによく理解しています。スタックオーバーフローの回答を関連させ、最新の状態を維持するために、今日の質問に答える方法があります。

私の元の質問の前提にはやや欠陥があります。 PIMPL-IDIOMを使用する理由は、コンパイラから実装の詳細を非表示にすることです。これは、不透明なポインター(宣言されたが定義されていないデータ型へのポインター)を介して実装を保存することによって行われます。これにより、クラスと対話してコンパイル時間をスピードアップする他のコンピレーションユニットが必要とするヘッダーの量を大幅に削減できます。私の質問のテンプレートの場合、実際にはどこでもemplのタイプを完全に定義する必要があるインスタンス化の時点でタイプtを完全に知っていることが必要です C<ImplType> この用語の古典的な意味でのPIMPL-IDIOMの例ではなく、これを明らかに使用することが使用されています。

プライベートポインターを介してクラスデータを保持する他の理由があります。たとえば、ノースローの動きとスワップを簡単に実装できるようになり、クラスが強力な例外保証を満たす必要がある場合にも適しています(Idiomのコピーとスワップを参照してください コピーアンドスワップイディオムとは何ですか?)。一方、インプルへのアクセスごとに間接的な層(しばしばキャッシュミスをもたらす)と、インプルの作成と破壊時にヒープの割り当て/取引を追加します。これらはかなりのパフォーマンスの罰則になる可能性があるため、このソリューションは銀の弾丸と見なされるべきではありません。

c ++ 11を使用できる場合は、std :: unique_ptrをboost :: scoped_ptrの代わりに使用する必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top