繁体   English   中英

在std :: set或std :: map的键中使用weak_ptr是否安全

[英]Is it safe to use a weak_ptr in a std::set or key of std::map

今天有很多关于std::weak_ptrstd::owner_less以及它们在关联容器std::setstd::map 有很多帖子声称在std::set中使用weak_ptr是不正确的,因为如果弱指针到期,它将是Undefined Behavior。 这个对吗?

std::owner_less存在的原因之一是提供这种排序,并在存在即将到期的弱指针时保证其安全性。 我的逻辑是

首先,定义std::owner_less

  • operator()定义了25.4中定义的严格弱排序

    operator() !operator()(a, b) && !operator()(b, a)定义的等价关系下,当且仅当它们共享所有权或者都是空的时,两个shared_ptrweak_ptr实例是等效的。

这两个案例是

  1. 它们共享同一个对象,实际上它们意味着它们共享相同的引用计数对象。
  2. 他们都是空的。

现在,我认为混乱是在第二个任期。 关键是标准中的“空”意味着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_ptrshared_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM