1. ホーム
  2. c++

[解決済み] スマートポインタ:オブジェクトは誰のものか?[クローズド]

2022-08-19 21:16:07

質問

C++はメモリ所有権がすべて - aka 所有権セマンティクス .

動的に割り当てられたメモリのチャンクの所有者は、そのメモリを解放する責任があります。ですから、問題は本当に誰がメモリを所有しているかになります。

C++では、所有権は ポインタの内側にラップされているため、優れた(IMO)C++プログラムでは、非常に稀です ( レア ではなく 決して のように、生のポインタが渡されるのを見ることはできません(生のポインタは所有者が推測できないため、誰がそのメモリを所有しているかがわからず、ドキュメントを注意深く読まないと、誰が所有権に責任があるのかがわかりません)。

逆に、生のポインタがクラス内に格納されているのを見るのは稀で、それぞれの生のポインタはそれ自身のスマートポインタラッパー内に格納されています。 ( N.B: オブジェクトを所有していない場合、いつスコープ外に出て破壊されるか分からないので、格納すべきではありません)。

そこで質問です。

  • 人々はどのような所有権の意味合いに遭遇したことがありますか?
  • それらのセマンティクスを実装するために、どのような標準クラスが使用されていますか?
  • どのような場面で有用だと感じますか?

回答ごとに1種類のセマンティック・オーナーシップを維持し、個別に投票できるようにしましょう。

要約です。

概念的には、スマート ポインターは単純であり、素朴な実装は簡単です。私は多くの実装を試したことがありますが、必ずと言っていいほど、カジュアルな使い方や例ではわからないような方法で壊れています。したがって、私は、自分でスマートポインタを作るよりも、ライブラリから十分にテストされたスマートポインタを常に使用することをお勧めします。 std::auto_ptr やBoostスマートポインタの1つは、私のすべてのニーズをカバーしているように見えます。

std::auto_ptr<T> :

一人がオブジェクトを所有する。所有権の譲渡は可能です。

使用方法 これにより、所有権の明示的な譲渡を示すインターフェースを定義することができます。

boost::scoped_ptr<T>

所有者は一人です。所有権の譲渡は認められません。

使用方法。所有権を明示的に示すために使用します。オブジェクトはデストラクタで破棄されるか、明示的にリセットされる。

boost::shared_ptr<T> ( std::tr1::shared_ptr<T> )

複数所有権です。これは単純な参照カウントのポインタです。参照カウントが0になると、そのオブジェクトは破棄されます。

使用方法 オブジェクトが、コンパイル時に決定できない寿命を持つ複数の所有者を持つことができる場合。

boost::weak_ptr<T> :

で使用される shared_ptr<T> で、ポインタの循環が起こりうる状況で使用されます。

使用方法 サイクルのみが共有Refcountを維持しているときに、サイクルがオブジェクトを保持するのを止めるために使用します。

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

私の場合、この3種類でほとんど用が足ります。

shared_ptr - 参照カウント式で、カウンタがゼロになると解放されます。

weak_ptr - 上記と同じですが、「スレーブ」として shared_ptr に対する「スレーブ」であるため、割り当てを解除することができません。

auto_ptr - 作成と割り当て解除が同じ関数内で行われる場合、またはオブジェクトが常に一人の所有者のみとみなされる必要がある場合です。あるポインターを別のポインターに割り当てるとき、2 番目のポインターは最初のポインターからオブジェクトを「盗む」のです。

私はこれらのために独自の実装を持っていますが、これらはまた Boost .

私は今でもオブジェクトを参照渡し ( const この場合、呼び出されたメソッドはオブジェクトが呼び出されている間だけ生きていると仮定しなければなりません。

と呼んでいる、私が使っているもう一つの種類のポインタがあります。 ハブ変数 . それは、その中にネストされたオブジェクトからアクセスできなければならないオブジェクトがある場合です(通常は仮想基底クラスとして)。これを解決するには weak_ptr を渡せばいいのですが、これには shared_ptr は持っていません。これらのオブジェクトが彼よりも長生きしないことを知っているので、hub_ptrを渡します(これは通常のポインタに対する単なるテンプレートラッパーです)。