C++ 11のベストプラクティスについて質問があります。 shared_ptrをクリアするとき、パラメータなしでreset()
関数を使用するか、shared_ptr
からnullptr
?例えば:
std::shared_ptr<std::string> foo(new std::string("foo"));
foo.reset();
foo = nullptr;
実際の違いはありますか、どちらのアプローチにも利点/欠点はありますか?
実際の違いはありますか、またはどちらのアプローチにも利点/欠点がありますか?
2つの選択肢は、2番目の形式(_foo = nullptr
_)が最初の形式で定義されているという意味で、完全に同等です。 C++ 11標準のパラグラフ20.7.1.2.3/8-10に従って:
_unique_ptr& operator=(nullptr_t) noexcept;
_8 Effects:
reset()
。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");
_
reset()
はインテントを通知するので好むでしょう。ただし、explicitly clear shared_ptr<>
、つまり、shared_ptr<>
は、他の方法でクリアするとスコープ外になります。
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()で何が起こったかを確認する方法がわからないので。どちらが速いかわかりません。