首页 > 解决方案 > std::shared_ptr 为空但不为空

问题描述

比较:std::shared_ptr 为空但不为空

std::shared_ptr<T>别名构造函数让我们玩有趣的游戏。上面的 SO 帖子讨论了第一个参数何时为std::shared_ptr<void>{nullptr}. 我对反向感兴趣。即使shared_ptr“是” nullptr(如果不是我们保留对它的引用,这将是完全无法访问的),这是否保证保持指向对象的活动?:

std::shared_ptr<S> ps = std::make_shared<S>();
auto& s = *ps; // Keep a reference to the S.
auto p = std::shared_ptr<S>(ps, nullptr); // Aliasing c'tor with null pointer.
ps = nullptr;
assert(ps == nullptr);
assert(p == nullptr);
foo(s); //< Is the S still alive here?

https://godbolt.org/z/M19s54

标签: c++shared-ptr

解决方案


是的,“空但不为空”shared_ptr将使对象保持活动状态,因为它与shared_ptr构造它的对象共享所有权。所有shared_ptr彼此共享所有权的 s 都会对存储在控制块中的原子引用计数做出贡献,并且只有当该引用计数达到零时,才会销毁拥有的对象。

对于标准语,请参阅 [util.smartptr.shared.const]/14:

template<class Y> shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept;
构造一个shared_ptr存储p和共享所有权的实例r

没有对p;的值指定任何约束。因此,它可能是任何有效的指针值,包括 null 甚至是结束指针(尽管我不确定您为什么要这样做)。

然后看[util.smartptr.shared.dest]/(1.1):

如果*this为空或与另一个shared_ptr实例共享所有权 ( use_count() > 1),则没有副作用。

换句话说,当ps被销毁时,它仍然与 共享所有权p,因此该对象还没有被销毁。

生成的对象在通常意义上并不是真的无法到达,因为它仍然可以销毁它。你不能用它做任何其他事情。


推荐阅读