Domanda

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?

È stato utile?

Soluzione

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

Altri suggerimenti

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.

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top