web-dev-qa-db-ja.com

C ++ 11 shared_ptrをクリアするとき、リセットを使用するかnullptrに設定する必要がありますか?

C++ 11のベストプラクティスについて質問があります。 shared_ptrをクリアするとき、パラメータなしでreset()関数を使用するか、shared_ptrからnullptr?例えば:

std::shared_ptr<std::string> foo(new std::string("foo"));
foo.reset();
foo = nullptr;

実際の違いはありますか、どちらのアプローチにも利点/欠点はありますか?

56
user1930581

実際の違いはありますか、またはどちらのアプローチにも利点/欠点がありますか?

2つの選択肢は、2番目の形式(_foo = nullptr_)が最初の形式で定義されているという意味で、完全に同等です。 C++ 11標準のパラグラフ20.7.1.2.3/8-10に従って:

_ unique_ptr& operator=(nullptr_t) noexcept;
_

8 Effectsreset()

9事後条件get() == nullptr

10Returns:_*this_。

したがって、意図を最も明確にするものを選択するだけです。個人的に、私は好む:

_foo = nullptr;
_

ポインタをnullにしたいことがより明確になるからです。ただし、一般的なアドバイスとして、スマートポインターを明示的にリセットする必要がある状況を最小限に抑えるようにしてください。


また、newを使用するのではなく:

_std::shared_ptr<std::string> foo(new std::string("foo"));
_

可能な場合、std::make_shared()の使用を検討してください。

_auto foo = std::make_shared<std::string>("foo");
_
72
Andy Prowl

reset()はインテントを通知するので好むでしょう。ただし、explicitly clear shared_ptr<>、つまり、shared_ptr<>は、他の方法でクリアするとスコープ外になります。

13
Walter

https://godbolt.org/ を使用してチェックする場合、それらは少し異なります
gcc(7.2)を使用して
foo.reset();はアセンブリコードを生成します

  lea rax, [rbp-32]
  mov rdi, rax
  call std::__shared_ptr<int, (__gnu_cxx::_Lock_policy)2>::reset()

しかしながら、 foo = nullptr;生成

  lea rax, [rbp-16]
  mov esi, 0
  mov rdi, rax
  call std::shared_ptr<int>::shared_ptr(decltype(nullptr))
  lea rdx, [rbp-16]
  lea rax, [rbp-32]
  mov rsi, rdx
  mov rdi, rax
  call std::shared_ptr<int>::operator=(std::shared_ptr<int>&&)
  lea rax, [rbp-16]
  mov rdi, rax
  call std::shared_ptr<int>::~shared_ptr()

Nullptrで共有ポインターを作成し、新しく作成されたオブジェクトを変数に割り当て、デストラクター文字列を呼び出すデストラクターを呼び出します。

関数reset()で何が起こったかを確認する方法がわからないので。どちらが速いかわかりません。

0
r0ng