重複の可能性があります:
pimpl:shared_ptrまたはunique_ptr
スマートポインタ(ブースト)の説明
Shared_ptrとunique_ptrの違いを説明できますか。
これらのクラスはどちらもスマートポインタです。つまり、ほとんどの場合、それらのオブジェクトが参照できなくなった時点で、それらが指しているオブジェクトの割り当てが自動的に解除されます。この2つの違いは、各タイプの異なるポインタがリソースを参照できる数です。
unique_ptr
を使用するとき、最大1つのunique_ptr
が任意の1つのリソースを指すことができます。そのunique_ptr
が破棄されると、リソースは自動的に再利用されます。どのリソースに対してもunique_ptr
は1つしか存在できないため、unique_ptr
のコピーを作成しようとすると、コンパイル時エラーが発生します。たとえば、このコードは違法です。
unique_ptr<T> myPtr(new T); // Okay
unique_ptr<T> myOtherPtr = myPtr; // Error: Can't copy unique_ptr
ただし、unique_ptr
は、新しい移動セマンティクスを使用して移動することができます。
unique_ptr<T> myPtr(new T); // Okay
unique_ptr<T> myOtherPtr = std::move(myPtr); // Okay, resource now stored in myOtherPtr
同様に、あなたはこのようなことをすることができます:
unique_ptr<T> MyFunction() {
unique_ptr<T> myPtr(/* ... */);
/* ... */
return myPtr;
}
この慣用句は、「管理対象リソースをあなたに返しています。戻り値を明示的に取得しないと、リソースがクリーンアップされます。取得した場合は、そのリソースの排他的所有権を持ちます。」このように、あなたはunique_ptr
をauto_ptr
のより安全でより良い置き換えとして考えることができます。
一方、shared_ptr
は、複数のポインタが特定のリソースを指すことを可能にします。リソースの最後のshared_ptr
が破棄されると、そのリソースは解放されます。たとえば、このコードは完全に合法です:
shared_ptr<T> myPtr(new T); // Okay
shared_ptr<T> myOtherPtr = myPtr; // Sure! Now have two pointers to the resource.
内部的には、shared_ptr
はリソースを参照するポインタの数を追跡するために 参照カウント を使用します。そのため、参照サイクルを導入しないように注意する必要があります。
要するに:
unique_ptr
を使用します。shared_ptr
を使用してください。お役に立てれば!
unique_ptr
は、どこかに動的オブジェクトがある場合に最適な軽量のスマートポインタです。one消費者は唯一の(したがって "ユニークな")責任を持ちます - おそらく動的にいくつかを維持する必要があるラッパークラスです。割り当てられたオブジェクトunique_ptr
はほとんどオーバーヘッドがありません。コピー可能ではありませんが、移動可能です。そのtypeはtemplate <typename D, typename Deleter> class unique_ptr;
なので、twoテンプレートパラメータに依存します。
unique_ptr
は、auto_ptr
が古いC++に含まれることを望んでいたものでもありますが、その言語の制限のためにできませんでした。
一方shared_ptr
は非常に異なる動物です。明らかな違いは、動的なオブジェクトに対する責任を共有する多くのコンシューマ(したがって「共有」)を持つことができ、そのオブジェクトはすべての共有ポインタがなくなったときにのみ破棄されるということです。加えて、あなたは観察しているweak pointersこれは彼らがフォローしている共有ポインタが消えたかどうかをインテリジェントに知らされるでしょう。
内部的には、shared_ptr
にはもっと多くのことがあります。参照カウントがあります。これは、並行コードでの使用を可能にするためにアトミックに更新されます。また、たくさんの割り当てが行われています。1つは内部簿記の「参照制御ブロック」用で、もう1つは(多くの場合)実際のメンバーオブジェクト用です。
しかし、もう1つ大きな違いがあります。共有ポインタ型は常にtemplate <typename T> class shared_ptr;
です。これはカスタム削除子を使用して初期化できるという事実にもかかわらず、およびカスタムアロケータを使用して初期化できます。デリミタとアロケータは型消去と仮想関数ディスパッチを使って追跡されます。これはクラスの内部的な重みを増しますが、削除とアロケーションの詳細に関係なく、型T
の異なる種類の共有ポインタはすべて互換性があります。したがって、彼らは詳細を消費者に負担をかけずに、「T
に対する責任の共有」という概念を真に表現しています。
shared_ptr
とunique_ptr
は両方とも値で渡されるように設計されています(一意のポインタに対する明らかな移動性要件があります)。オーバーヘッドについて心配する必要はありません。それらの能力は本当に驚くべきものです。ただし、選択肢がある場合はunique_ptr
を選択し、本当に責任を共有する必要がある場合はshared_ptr
のみを使用してください。
nique_ptr
は、オブジェクトを排他的に所有するスマートポインタです。
shared_ptr
は共有所有権のためのスマートポインタです。 copyable
とmovable
の両方です。複数のスマートポインタインスタンスが同じリソースを所有できます。リソースを所有している最後のスマートポインタが範囲外になるとすぐに、リソースは解放されます。
unique_ptr
でポインタをラップするとき、unique_ptr
の複数のコピーを持つことはできません。 shared_ptr
は、格納されているポインタのコピー数をカウントする参照カウンタを保持します。 shared_ptr
がコピーされるたびに、このカウンタはインクリメントされます。 shared_ptr
が破棄されるたびに、このカウンタはデクリメントされます。このカウンタが0に達すると、格納されているオブジェクトは破棄されます。