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()中发生了什么。 看不到哪一个更快。