C + + 11当清除 share_ptr 时,我应该使用复位还是设置为 nullptr?

我有一个关于 C + + 11最佳实践的问题。当清除 share _ ptr 时,我应该使用没有参数的 reset()函数,还是应该将 shared_ptr设置为 nullptr?例如:

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

这两种方法有什么真正的区别吗? 或者有什么优缺点吗?

93180 次浏览

Generally, smart pointers can handle themselves. But if you need a solution, the reset() is, in my opinion, your best bet.

Is there any real difference, or are there advantages/disadvantages to either approach?

The two alternatives are absolutely equivalent, in the sense that the second form (foo = nullptr) is defined in terms of the first one. Per Paragraph 20.7.1.2.3/8-10 of the C++11 Standard:

 unique_ptr& operator=(nullptr_t) noexcept;

8 Effects: reset().

9 Postcondition: get() == nullptr

10 Returns: *this.

Therefore, just choose the one which makes its intent clearest for you. Personally, I prefer:

foo = nullptr;

Because it makes it more evident that we want the pointer to be null. As a general advice, however, try to minimize the situations where you need to explicitly reset a smart pointer.


Besides, rather than using new:

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

Consider using std::make_shared() when possible:

auto foo = std::make_shared<std::string>("foo");

I would prefer reset() as it signals the intent. However, try to write your code such that you do not need to explicitly clear a shared_ptr<>, i.e. ensure that a shared_ptr<> goes out of scope when you would otherwise clear it.

They have a bit different if you use https://godbolt.org/ to check
by using gcc(7.2)
foo.reset(); generates assembly code

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

however, foo = nullptr; generates

  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()

It creates a shared pointer with nullptr, assign the newly created object to the variable and calls destructor to destory string.

Since I don't know how to check what happened in the function reset(). Can not see which is faster.