[英]Is it safe to use a weak_ptr in a std::set or key of std::map
今天有很多关于std::weak_ptr
和std::owner_less
以及它们在关联容器std::set
和std::map
。 有很多帖子声称在std::set
中使用weak_ptr
是不正确的,因为如果弱指针到期,它将是Undefined Behavior。 这个对吗?
std::owner_less
存在的原因之一是提供这种排序,并在存在即将到期的弱指针时保证其安全性。 我的逻辑是
首先,定义std::owner_less
operator()定义了25.4中定义的严格弱排序
在
operator()
!operator()(a, b) && !operator()(b, a)
定义的等价关系下,当且仅当它们共享所有权或者都是空的时,两个shared_ptr
或weak_ptr
实例是等效的。
这两个案例是
现在,我认为混乱是在第二个任期。 关键是标准中的“空”意味着weak_ptr
不与任何对象共享所有权。 同样,标准规定
constexpr weak_ptr() noexcept;
效果:构造一个空的
weak_ptr
对象。
后置条件:use_count() == 0
。weak_ptr(const weak_ptr& r) noexcept;
template<class Y> weak_ptr(const weak_ptr<Y>& r) noexcept;
template<class Y> weak_ptr(const shared_ptr<Y>& r) noexcept;
要求:除非
Y*
可隐式转换为T*
否则第二个和第三个构造函数不应参与重载决策。效果:如果
r
为空,则构造一个空的weak_ptr
对象; 否则,构造一个与r
共享所有权的weak_ptr
对象,并存储存储在r
中的指针的副本。后置条件:
use_count() == r.use_count()
。
Swap定义为交换两个weak_ptr
的状态,赋值定义为使用上面的构造函数和swap。
这里需要注意的是,创建空weak_ptr
的唯一方法是默认构造它,或者从先前为空的weak_ptr
或shared_ptr
复制/移动/分配一个。 同样重要的是要注意,你不能得到一个空weak_ptr
通过简单地让weak_ptr
到期。 过期的weak_ptr
只有一个use_count
为零。
实际上,当创建shared_ptr
时,必须创建引用计数对象,或者使用shared_ptr
构造函数与数据分开,或者在使用std::make_shared
时在相同的内存分配中创建引用计数对象。 当从该shared_ptr
构造weak_ptr
,它将指向相同的控制结构和引用计数。 当shared_ptr
被销毁时,它可能会破坏数据,但引用计数对象必须保留,直到删除共享所有权的所有weak_ptr
。 否则, weak_ptr
将有一个悬空指针引用。
所以,所有这些结合在一起意味着使用std::weak_ptr
作为std::map
键或std::set
,只要你使用std::owner_less
来执行排序。 上面保证weak_ptr
的顺序将保持不变,即使它在容器中它到期时也是如此。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.