1. ホーム
  2. c++

[解決済み】どのような時にどのようなポインタを使えばいいのでしょうか?

2022-04-04 14:15:22

質問

よし、じゃあこの前、生活のためにC++を書いたんだ。 std::auto_ptr はstd libにあるすべての利用可能なものであり boost::shared_ptr が大流行でした。私は、boostが提供する他のスマートポインタの型については、あまり調べたことがありませんでした。C++11では、boostが提供した型のいくつかが提供されるようになりましたが、すべてではありません。

そこで、どのスマートポインタをいつ使うかを判断する簡単なアルゴリズムをお持ちの方はいらっしゃいますか?できれば、ダムポインタ(例えば T* ) と残りのブースト・スマートポインタです。(例えば これ があれば最高です)。

解決方法は?

所有権を共有する。

shared_ptrweak_ptr が標準的に採用されているのは、その ブースト対応 . リソースを共有する必要があり、どれが最後の生き残りになるかわからない場合に使用します。使用方法 weak_ptr は、サイクルを中断するためではなく、共有リソースの寿命に影響を与えることなく、そのリソースを観察するために使用します。サイクルは shared_ptr 通常、2つのリソースがお互いを所有することはできません。

なお、Boostではさらに shared_array の適切な代替品になるかもしれません。 shared_ptr<std::vector<T> const> .

次に、Boost が提供する intrusive_ptr は、リソースがすでに参照カウント管理を提供しており、それをRAIIの原則に採用したい場合の軽量なソリューションです。こちらは規格に採用されなかった。

一意の所有権。

ブーストはまた scoped_ptr これはコピー不可で、削除子も指定できない。 std::unique_ptrboost::scoped_ptr ステロイドを使用した、あなたの スマートなポインタが必要なときのデフォルトの選択 . これはテンプレート引数でデレタを指定することができ、また 移動可能 とは異なり boost::scoped_ptr . また、STLコンテナでも、コピー可能な型を必要とする操作を使用しない限り、完全に使用可能です(当然ですが)。

Boostには配列版があることに再度注意してください。 scoped_array を要求することで、統一されています。 std::unique_ptr<T[]> となる部分特殊化 delete[] の代わりにポインタを delete を使用します。 default_delete r). std::unique_ptr<T[]> も提供しています。 operator[] の代わりに operator*operator-> .

なお std::auto_ptr はまだ規格に残っていますが、それは 非推奨 . §D.10 [depr.auto.ptr]

クラステンプレート auto_ptr は非推奨です。[ 注意 クラステンプレート unique_ptr (20.7.1)はより良い解決策を提供します。 -終了メモ ]

所有権がない。

にはダムポインタ(生ポインタ)またはリファレンスを使用します。 非所有の参照 をリソースに適用することが分かっている場合や リソースが長持ちする 参照するオブジェクト/スコープを指定します。参照するオブジェクトやスコープを優先し、ヌルやリセットの可能性がある場合は生のポインタを使用します。

リソースへの非所有者の参照が必要だが、そのリソースがそれを参照するオブジェクトより長生きするかどうかわからない場合、そのリソースを shared_ptr を使用し weak_ptr - を使用すると、親の shared_ptr が生きていることを lock を返します。 shared_ptr は、そのリソースがまだ存在する場合は非NULLです。リソースが死んだかどうかをテストしたい場合は expired . この 2 つは似ているように聞こえますが、同時実行の前では非常に異なっています。 expired は、その1つの文の戻り値しか保証していません。一見、何の変哲もない

if(!wptr.expired())
  something_assuming_the_resource_is_still_alive();

は潜在的なレースコンディションです。