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; 

有没有真正的区别,还是有两个方法的优点/缺点?

有没有真正的区别,还是有两个方法的优点/缺点?

这两种select是绝对等价的,就第二种forms而言( foo = nullptr )是用第一种forms定义的。 根据C ++ 11标准的第20.7.1.2.3 / 8-10段:

  unique_ptr& operator=(nullptr_t) noexcept; 

8 效果reset()

9 后置条件get() == nullptr

10 返回*this

因此, 只要select一个最明确的目标 。 我个人更喜欢:

 foo = nullptr; 

因为它使得我们希望指针变为null更明显。 然而,作为一般build议,尽量减less需要显式重置智能指针的情况。


此外,而不是使用new

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

考虑尽可能使用std::make_shared()

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

我更喜欢reset()因为它表示意图。 但是,尝试编写代码,以便不需要显式清除shared_ptr<> ,即确保shared_prt<>超出范围,否则将清除它。

通常,智能指针可以处理自己。 但是如果你需要一个解决scheme,在我看来, reset()是你最好的select。

如果您使用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创build一个共享指针,将新创build的对象分配给该variables,并将析构函数调用为destorystring。

因为我不知道如何检查函数reset()中发生了什么。 看不到哪一个更快。