次のように定義された関数があります。
void foo(std::shared_ptr<X> x) { ... };
X
に共有ptrを宣言した場合:
std::shared_ptr<X> sourcePtr(new X(...));
次に、次のようにfoo
を呼び出します。
foo(std::move(sourcePtr));
または
foo(sourcePtr);
最初のオプションを使用すると、sourcePtr
がヌルになることを理解しています。また、参照カウントが増加するのを防ぎますか?
それが問題にならない場合、どのオプションを優先すべきですか?そのような決定をするとき、私は他に何かを考慮すべきですか?
はい、共有ポインターを関数に移動すると、次のようになります。
元のsourcePtr
はnullになり、
参照カウントは変更されません。
関数呼び出し後にsourcePtr
の値が不要になることがわかっている場合、それを関数に移動すると、atomic増分(およびその後の減分)が保存されるため、わずかに最適化されます。 sourcePtr
が範囲外になるとき)。
ただし、識別子sourcePtr
は、nullポインタを保持しているだけで、スコープの残りの部分で引き続き有効であることに注意してください。つまり、移動後にコンパイラを使用しても文句は言われませんが、移動元を忘れると、おそらくnullを逆参照することになります。私はこの「最適化」move
を頻繁に使用する傾向があり、何度か噛まれました。機能に追加の機能が追加され、move
を元に戻すのを忘れた場合、ニースクラッシュが発生します。
したがって、不要になった場合の移動は、わずかな最適化とわずかなメンテナンスの負担です。あなたの場合、どちらがより重要かを判断するのはあなた次第です。
上記は、宣言とsourcePtr
の最後の呼び出しの間に実際にfoo
を使用するコードがあることを前提としています(@WhozCraigに感謝します)。ない場合は、much呼び出しサイトでポインタを作成する方が良いでしょう:
foo(std::make_shared<X>(...));
このようにして、同じ量のアトミック操作を保存します。and潜在的に危険な空の共有ポインターが存在しません。