Should I pass a shared_ptr by reference? [duplicate] Ask Question

Should I pass a shared_ptr by reference? [duplicate] Ask Question

What are the best practices for passing a shared_ptr?

Currently I pass shared_ptr function arguments like so:

void function1( shared_ptr<TYPE>& value );

ベストアンサー1

In controlled circumstances you can pass the shared pointer by constant reference. Be sure that nobody is concurrently deleting the object, though this shouldn't be too hard if you're careful about to whom you give references.

In general, you should pass the shared pointer as a straight copy. This gives it its intended semantics: Every scope that contains a copy of the shared pointer keeps the object alive by virtue of its "share" in the ownership.

The only reason not to always pass by value is that copying a shared pointer comes at a certain price on account of the atomic reference count update; however, this might not be a major concern.


Optional digression:

Since the main question has been answered, perhaps it is instructive to consider a few ways in which you should never use a shared pointer. Here is a little thought experiment. Let us define a shared pointer type SF = std::shared_ptr<Foo>. In order to consider references, rather than passing function arguments let us look at the type RSF = std::reference_wrapper<T>. That is, if we have a shared pointer SF p(std::make_shared<Foo>());, then we can make a reference wrapper with value semantics via RSF w = std::ref(p);. So much for the setup.

今では誰もがポインタのコンテナが地雷原であることを知っています。そのため、メンテナンス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つのかなり不自然な例が、共有ポインタを実際にどのように渡したいのかを少しでも明らかにしてくれることを願っています。コピー適切に設計されたプログラムでは、どのリソースに対して誰が責任を持つかが常に明確である必要があり、共有ポインターは適切に使用すれば、その目的に最適なツールとなります。

おすすめ記事