2011-12-05 8 views
6

私は通常PIMPL年代のためのブースト:: scoped_ptrをを使用しますscoped_ptrのデストラクタの要件を満たすためにimplが完全に定義されているcppファイル。それはとにかく動作しますが、私はそれが保証されているかどうか、またはちょうどうまくいくかどうかはわかりません。いくつかの「ベストプラクティス」または標準がありますか? scoped_ptrは、コピー可能でないクラスのpimplsに最適なスマートポインタですか?テンプレート内のpimpl-idiom。どのスマートポインタ? (その後、私は驚きを得ることはありませんので、私はコピーコンストラクタに対処するのを忘れた場合一つの理由のために)私はちょうどでデストラクタを置くことはできませんが、テンプレートで</p> <p>を

template <class T> class C { 
public: 
    C(){} 
    ~C(){} 
private: 
    boost::scoped_ptr<T> pimpl_; 
}; 
+4

この種のPIMPL実装は意味を持ちません。なぜなら、Cテンプレートをインスタンス化するためには、タイプTについて知っておく必要があるからです.PPIMPLは、ユーザから同等のTを完全に隠すためです。 –

+0

@VladLazarenkoええと、私はboost :: scoped_ptrもあらかじめ宣言されたクラスで動作すると考えました。この場合、Tが定義されているか、事前に宣言されているかによって異なります。 –

+0

@DavidFeurle:このテンプレートが動作するためには、 'T'のサイズとそのインタフェースは、次のようにしなければなりません。例えば、あなたは 'new T()'をどこで呼び出すのですか?それはテンプレート内になければならないので "cpp"ファイルに隠すことはできませんので、PIMPLではありません –

答えて

1

boost::shared_ptrは でインスタンス化—の地点以外での完全な定義を必要としません。コンストラクタ、 の場合はpimpl。 boost::shared_ptrであり、非常に予期しないセマンティクス(割り当てまたはコピーのために参照セマンティクス )を与えるので、 しかし、は、pimplイディオムには適していません。 スマートポインタの複雑さを本当に増やしたい場合は、はデストラクタが である点で完全定義が必要です)boost::scoped_ptrがより適切です。

テンプレートに関しては、 のpimplイディオムをヘッダーから実装することは意味がありません。 exportがなければ、 クラステンプレートの実装の詳細は全て テンプレートを使用しなければならないので、pimpl イディオムの背後にある動機はなくなります。

13

ちょうどハーブ・サッターが長い時間後に彼のGotWsを書き直し始めたことが起こりました。最初の新機能の1つは、 "Compilation Firewalls"に関連しています。あなたが見てみましょうすることをお勧めします

GotW #100: Compilation Firewalls (Difficulty: 6/10)

GotW #101: Compilation Firewalls, Part 2 (Difficulty: 8/10)

+0

私は彼の本が大好きですunique_ptrを使ってどのポインタタイプを使うべきか質問してきたようです – odinthenerd

+0

: unique_ptr pimpl' – sehe

+1

ハーブがもっと複​​雑になっているように見えますが、より良い哲学です。彼の標準ベースのソリューションはすべて、実際の利益が得られないほど複雑です。 –

2

2年後、私は状況をよりよく理解しています。スタックオーバフローの回答を適切に保つために、ここで今日の質問にどのように答えるかが重要です。

私の元の質問の前提には多少の欠陥があります。 pimpl-idiomを使用する理由は、実装の詳細をコンパイラから隠すためです。これは、不透明ポインタ(宣言されているが定義されていないデータ型へのポインタ)を介して実装を格納することによって行われます。これにより、クラスと相互作用する他のコンパイルユニットが必要とするヘッダの量を大幅に減らすことができ、コンパイル時間を短縮することができます。私の質問のテンプレートの場合は、実際にimplの型がC<ImplType>が使用されているところで完全に定義されている必要があるインスタンス化の時点で型Tを完全に知っている必要があります。これは明らかにpimpl-idiomの例ではありませんこの言葉の古典的な意味で。

プライベートポインタを介してクラスデータを保持する理由は他にもあります。たとえば、ノースロームーブとスワップを簡単に実装できます。また、クラスが強力な例外保証を満たす必要がある場合にも適していますスワップイディオムWhat is the copy-and-swap idiom?)。一方、インプリメンテーションへのアクセスごとにインダイレクションの層(キャッシュミスを招くことが多い)を追加し、インプリメンテーションの作成と破棄時にヒープの割り当て/割り当て解除を追加します。これらはかなりのパフォーマンス上の罰則になる可能性があります。したがって、この解決策は銀色の弾丸と見なされるべきではありません。

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

関連する問題

 関連する問題