1. ホーム
  2. c++

[解決済み] shared_ptrを参照渡しした方が良いですか?重複

2022-08-03 01:25:36

質問

shared_ptrを渡すためのベストプラクティスは何ですか?

現在、私はshared_ptr関数の引数をこのように渡しています。

void function1( shared_ptr<TYPE>& value );

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

制御された環境では、共有ポインタを 定数参照 . ただし、オブジェクトを同時に削除する人がいないことを確認する必要があります。

一般的には、共有ポインタをそのまま コピー . これにより、意図されたセマンティクスが得られます。共有ポインタのコピーを含むすべてのスコープは、所有権におけるその "share" によって、オブジェクトを保持し続けます。

常に値で渡さない唯一の理由は、共有ポインタのコピーがアトミックな参照カウントの更新のために一定の代償を伴うということです。


オプションの余談です。

主な質問には答えられたので、おそらくあなたがすべきいくつかの方法を検討することは有益です。 決して 共有ポインタを使用する必要があります。ここでちょっとした思考実験をしてみましょう。共有ポインタの型を定義してみましょう SF = std::shared_ptr<Foo> . 関数の引数を渡すのではなく、参照を考慮するために、この型を見てみましょう。 RSF = std::reference_wrapper<T> . つまり,共有ポインタ SF p(std::make_shared<Foo>()); を使えば、値のセマンティクスを持つ参照ラッパーを作ることができます。 RSF w = std::ref(p); . 設定はこれくらいにしておきましょう。

さて、ポインターのコンテナは地雷原であることは誰もが知っています。そこで std::vector<Foo*> は維持するのが悪夢のようなもので、不適切な寿命管理からいくつものバグが発生します。概念的にもっと悪いのは、誰が を所有する が明確でないことです。ポインタは、動的オブジェクト、自動オブジェクト、およびゴミへのポインタが混在している可能性さえあります。誰もそれを知ることはできません。そこで、標準的な解決策としては std::vector<SF> を代わりに使うことです。これが「共有ポインタの正しい使い方」です。一方、絶対に使ってはいけないのは std::vector<RSF> -- これは管理不可能な怪物で、実は元の裸のポインタのベクトルと非常によく似ているのです! 例えば、参照を保持しているオブジェクトがまだ生きているかどうかが不明な場合です。共有ポインターの参照を取ることは、その目的全体を破ってしまったのです。

2つ目の例として、共有ポインタがあるとします SF p があるとします。ここで、関数 int foo(SF) を同時に実行させたいとします。通常の std::thread(foo, p) はうまく機能します。スレッドコンストラクタが コピー を作成するからです。しかし、もし私たちが std::thread(foo, std::ref(p)) と言っていたら、大変なことになっていたでしょう。呼び出し側のスコープにある共有ポインタが期限切れになってオブジェクトが破壊され、ぶら下がった参照と無効なポインタが残ることになります!

これらの 2 つのかなり不自然な例から、共有ポインターを本当に コピー . うまく設計されたプログラムでは、誰がどのリソースに責任を持つかは常に明確であるべきで、正しく使用された場合、共有ポインターはそのための素晴らしいツールです。