重複の可能性:
pimpl: shared_ptr または unique_ptr
スマート ポインター (ブースト) の説明
誰かが shared_ptr と unique_ptr の違いを説明できますか?
重複の可能性:
pimpl: shared_ptr または unique_ptr
スマート ポインター (ブースト) の説明
誰かが shared_ptr と unique_ptr の違いを説明できますか?
これらのクラスは両方ともスマート ポインターです。つまり、オブジェクトが参照できなくなると、それらは (ほとんどの場合) 自動的に、それらが指しているオブジェクトの割り当てを解除します。2 つの違いは、リソースを参照できる各タイプの異なるポインターの数です。
を使用する場合、任意の 1 つのリソースを指すのはunique_ptr
最大 1つです。unique_ptr
それ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
1人の消費者が唯一の(したがって「一意の」)責任を負う動的オブジェクトがどこかにある場合、軽量のスマートポインターが選択されます-おそらく、動的に割り当てられたオブジェクトを維持する必要があるラッパークラスです。unique_ptr
オーバーヘッドはほとんどありません。コピー可能ではありませんが、移動可能です。その型はであるため、 2 つのテンプレート パラメータtemplate <typename D, typename Deleter> class unique_ptr;
に依存します。
unique_ptr
またauto_ptr
、古い C++ に入れたかったのですが、その言語の制限のためにできませんでした。
shared_ptr
一方、非常に異なる動物です。明らかな違いは、多くのコンシューマーが動的オブジェクトの責任を共有できること (つまり「共有」) であり、すべての共有ポインターがなくなったときにのみオブジェクトが破棄されることです。さらに、フォローしている共有ポインターが消えた場合にインテリジェントに通知される弱いポインターを監視することができます。
内部的にshared_ptr
は、さらに多くの処理が行われています: 同時実行コードで使用できるようにアトミックに更新される参照カウントがあります。また、多くの割り当てが行われています。1 つは内部簿記の「参照制御ブロック」用で、もう 1 つは (多くの場合) 実際のメンバー オブジェクト用です。
しかし、もう 1 つの大きな違いがあります。共有ポインターの型は常にです。これは、カスタムのデリータ とtemplate <typename T> class shared_ptr;
カスタムのアロケータを使用して初期化できるという事実にもかかわらずです。デリータとアロケータは、型の消去と仮想関数のディスパッチを使用して追跡されます。これにより、クラスの内部的な重みが増しますが、削除と割り当ての詳細に関係なく、さまざまな種類の型の共有ポインタがすべて互換性があるという大きな利点があります。したがって、消費者に詳細な負担をかけることなく、「責任の共有」の概念を真に表現しています。T
T
shared_ptr
とはどちらも、unique_ptr
値渡しされるように設計されています (一意のポインターに対する明らかな移動可能性要件があります)。それらのパワーは本当に驚異的であるため、どちらもオーバーヘッドを心配する必要はありませんが、選択肢がある場合は、 を優先し、本当に共有責任が必要な場合unique_ptr
にのみ使用してください。shared_ptr
unique_ptr
は、オブジェクトを排他的に所有するスマート ポインターです。
shared_ptr
は共有所有権のスマート ポインターです。copyable
との両方movable
です。複数のスマート ポインター インスタンスが同じリソースを所有できます。リソースを所有する最後のスマート ポインターが範囲外になるとすぐに、リソースは解放されます。
でポインタをラップする場合、 のunique_ptr
複数のコピーを持つことはできませんunique_ptr
。はshared_ptr
、格納されたポインターのコピーの数をカウントする参照カウンターを保持します。shared_ptr
aがコピーされるたびに、このカウンターがインクリメントされます。shared_ptr
aが破壊されるたびに、このカウンターはデクリメントされます。このカウンタが 0 になると、格納されたオブジェクトは破棄されます。