1. ホーム
  2. c++

[解決済み】スマートポインタ(boost)の説明

2022-04-05 13:55:15

質問

次のポインターのセットは何が違うのでしょうか?それぞれのポインターをプロダクションコードで使用するとしたら、どのような場合ですか?

例を挙げていただけるとありがたいです。

  1. scoped_ptr

  2. shared_ptr

  3. weak_ptr

  4. intrusive_ptr

プロダクションコードでboostを使用していますか?

どのように解決するのですか?

スマートポインタの基本特性

各スマートポインタに割り当てるプロパティがあれば、簡単です。重要なプロパティは3つあります。

  • 所有権なし
  • 所有権移転
  • 所有権分担

1つ目の意味は、スマートポインターはオブジェクトを所有していないため、オブジェクトを削除できないことです。2つ目は、スマートポインタは同時に1つしか同じオブジェクトを指すことができないことを意味します。スマートポインタが関数から返される場合、所有権は返されたスマートポインタに移される、といった具合です。

3つ目は、複数のスマートポインタが同時に同じオブジェクトを指すことができることを意味します。これは ローポインター しかし、生ポインターには重要な特徴がありません。それは 所有 を使うかどうかです。所有権共有型スマートポインタは、すべての所有者がオブジェクトを手放した場合、そのオブジェクトを削除します。この動作はたまたま頻繁に必要になるため、所有権共有型スマートポインタは広く普及しています。

いくつかの所有型スマートポインタは、2番目と3番目のどちらもサポートしていません。そのため、関数から返したり、どこかに渡したりすることができません。どちらが最も適しているかというと RAII スマートポインタがローカルに保持され、オブジェクトがスコープ外に出た後に解放されるように作成されるだけである場合。

所有権の共有は、コピーコンストラクタを持つことで実装できます。これは当然スマートポインタをコピーし、コピーとオリジナルの両方が同じオブジェクトを参照することになります。C++では、あるオブジェクトから別のオブジェクトに何かを転送する手段がサポートされていないため、所有権の移転は現在のところ実際に実装することはできません。関数からオブジェクトを返そうとすると、そのオブジェクトはコピーされてしまいます。つまり、所有権の移動を実装したスマートポインタは、その所有権の移動を実装するためにコピーコンストラクタを使用しなければならないのです。なぜなら、コンテナの要素のコピーコンストラクタの動作は、スマートポインタのいわゆる「移動コンストラクタ」の動作と互換性がないからです。

C++1x では、いわゆる "move コンストラクタおよび "move 代入演算子を導入することにより、所有権移動のネイティブ サポートが提供されます。また、このような所有権移動スマート ポインターは unique_ptr .

スマートポインタの分類

scoped_ptr は、転送も共有もできないスマートポインタです。局所的にメモリを確保する必要がある場合にのみ使用可能ですが、スコープ外に出た場合は必ず再度解放するようにしてください。しかし、他の scoped_ptr とスワップしたい場合は、スワップすることができます。

shared_ptr は所有権を共有するスマートポインタです(上記3種類目)。参照カウントされるので、最後のコピーがスコープ外に出たときに、管理されているオブジェクトを解放することができます。

weak_ptr は非所有型スマートポインタです。これは、(shared_ptrによって管理されている)管理対象オブジェクトを参照カウントを追加せずに参照するために使用されます。通常、shared_ptrから生のポインタを取り出して、それをコピーする必要があります。しかし、それでは、オブジェクトが実際に削除されたときに確認する方法がないため、安全ではありません。そこで weak_ptr は shared_ptr が管理するオブジェクトを参照することで、その手段を提供します。もし、そのオブジェクトにアクセスする必要があれば、そのオブジェクトの管理をロックし(そのオブジェクトを使用している間に他のスレッドで shared_ptr がそれを解放することを避けるため)、それから使用することができます。weak_ptr が既に削除されたオブジェクトを指している場合は、例外を投げて通知します。weak_ptr の使用は、循環的な参照がある場合に最も有益です。参照カウントはこのような状況に容易に対応することができません。

intrusive_ptr はshared_ptrのようなものですが、参照カウントをshared_ptrに保持せず、カウントの増減は管理対象のオブジェクトが定義する必要があるいくつかのヘルパー関数に任せます。これは、すでに参照されているオブジェクト(外部の参照カウント機構によって参照カウントが増加する)をintrusive_ptrに詰め込むことができるという利点があります - 参照カウントはもうスマートポインタの内部ではなく、スマートポインタは既存の参照カウント機構を使用するためです。

unique_ptr は所有権移転ポインタです。コピーすることはできませんが、C++1x の移動コンストラクタを使用することで移動させることができます。

unique_ptr<type> p(new type);
unique_ptr<type> q(p); // not legal!
unique_ptr<type> r(move(p)); // legal. p is now empty, but r owns the object
unique_ptr<type> s(function_returning_a_unique_ptr()); // legal!

これは,std::auto_ptr が従うセマンティックですが,移動のネイティブサポートが欠落しているため,落とし穴なしにそれらを提供することができません.C++1x では、移動のみ可能でコピー不可能なオブジェクトをコンテナに格納することも可能になります。つまり、例えばvectorの中にunique_ptrを詰め込むことができるわけです。ここでやめて、以下を参照することにする。 いい記事 これについては、もっと詳しく知りたい方は、こちらをご覧ください。