我对C ++ 11最佳做法有疑问。清除shared_ptr时,应使用reset()
不带参数的函数,还是应将设置shared_ptr
为nullptr
?例如:
std::shared_ptr<std::string> foo(new std::string("foo"));
foo.reset();
foo = nullptr;
两种方法有什么真正的区别,还是有优点/缺点?
我对C ++ 11最佳做法有疑问。清除shared_ptr时,应使用reset()
不带参数的函数,还是应将设置shared_ptr
为nullptr
?例如:
std::shared_ptr<std::string> foo(new std::string("foo"));
foo.reset();
foo = nullptr;
两种方法有什么真正的区别,还是有优点/缺点?
std::shared_ptr<std::string> bar; foo = bar
?通常,当我们将shared_ptr分配给另一个对象时,它指向的对象的引用计数会增加。在这种情况下会发生什么?
Answers:
两种方法有什么真正的区别,还是有优点/缺点?
在第二种形式(foo = nullptr
)是根据第一种形式定义的意义上,这两种选择是绝对等价的。根据C ++ 11标准第20.7.1.2.3 / 8-10段:
unique_ptr& operator=(nullptr_t) noexcept;
8种效果:
reset()
。9后置条件:
get() == nullptr
10返回:
*this
。
因此,只需选择一个对您最清楚的意图。就个人而言,我更喜欢:
foo = nullptr;
因为它使我们希望指针为空更加明显。但是,作为一般建议,请尽量减少需要显式重置智能指针的情况。
此外,而不是使用new
:
std::shared_ptr<std::string> foo(new std::string("foo"));
考虑std::make_shared()
在可能的情况下使用:
auto foo = std::make_shared<std::string>("foo");
unique_ptr
,也没有operator=(nullptr_t)
针对的方法shared_ptr
。是正确的吗,如果我使用的话,nullptr
将被强制转换为unique_ptr
然后强制转换为?shared_ptr
foo = nullptr
shared_ptr
没有operator=(nullptr_t)
,因此分配nullptr
给它需要转换。我们可能会证明,在优化的构建中这并不重要,但要说“这两种选择是绝对等价的,因为第二种形式(foo = nullptr)是根据第一种形式定义的”,这似乎是完全错误的
如果您使用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创建一个共享指针,将新创建的对象分配给该变量,并将destructor调用到destory字符串。
由于我不知道如何检查函数reset()中发生了什么。看不清楚哪个更快。
通常,智能指针可以处理自己。但是,如果您需要解决方案,那么reset()
我认为这是您的最佳选择。
foo = {}
也可以选择!