C++11 When clearing shared_ptr, should I use reset or set to nullptr?

C++C++11Shared PtrResetNullptr

C++ Problem Overview


I have a question about C++11 best practices. When clearing a shared_ptr, should I use the reset() function with no parameter, or should I set the shared_ptr to nullptr? For example:

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

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

C++ Solutions


Solution 1 - C++

> 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");

Solution 2 - C++

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.

Solution 3 - C++

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.

Solution 4 - C++

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1930581View Question on Stackoverflow
Solution 1 - C++Andy ProwlView Answer on Stackoverflow
Solution 2 - C++WalterView Answer on Stackoverflow
Solution 3 - C++r0n9View Answer on Stackoverflow
Solution 4 - C++XaltarView Answer on Stackoverflow