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

标签 c++ c++11 weak-ptr

今天有很多关于 std::weak_ptrstd::owner_less 以及它们在关联容器 std::set< 中的使用的问题std::map。有许多帖子指出在 std::set 中使用 weak_ptr 是不正确的,因为如果弱指针过期,它将是未定义的行为。这是正确的吗?

最佳答案

原因之一std::owner_less exists 是为了提供这种排序,并在存在过期弱指针的情况下保证其安全。我的逻辑是

一、std::owner_less的定义

  • operator() defines a strict weak ordering as defined in 25.4

    under the equivalence relation defined by operator(), !operator()(a, b) && !operator()(b, a), two shared_ptr or weak_ptr instances are equivalent if and only if they share ownership or are both empty.

两种情况是

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

现在,我认为困惑是在第二个任期。关键是标准中的“空”意味着 weak_ptr不与任何对象共享所有权。同样,标准规定

  • constexpr weak_ptr() noexcept;

    Effects: Constructs an empty weak_ptr object.
    Postconditions: 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;

    Requires: The second and third constructors shall not participate in the overload resolution unless Y* is implicitly convertible to T*.

    Effects: If r is empty, constructs an empty weak_ptr object; otherwise, constructs a weak_ptr object that shares ownership with r and stores a copy of the pointer stored in r.

    Postconditions: use_count() == r.use_count().

交换定义为交换两个weak_ptr的状态s,并且赋值被定义为使用上面的构造函数和交换。

这里要注意的是,唯一的方法是创建一个空的 weak_ptr是默认构造它,或者从以前空的 weak_ptr 复制/移动/分配一个或 shared_ptr .同样重要的是要注意你不能得到一个空的 weak_ptr通过简单地让 weak_ptr到期。一个过期的weak_ptr只是有一个 use_count为零。

作为一个实际问题,当一个 shared_ptr创建时,必须创建一个引用计数对象,或者使用 shared_ptr 与数据分开构造函数,或在相同的内存分配时 std::make_shared用来。当 weak_ptrshared_ptr 构成,它将指向相同的控制结构和引用计数。当 shared_ptr被销毁,它可能会销毁数据,但引用计数对象必须保留直到所有 weak_ptr该股份所有权被删除。否则,weak_ptr会有一个悬空指针引用。

因此,所有这些加在一起意味着使用 std::weak_ptr 是安全的因为他们是 std::map 的关键或者在 std::set , 只要你使用 std::owner_less执行排序。以上保证了 weak_ptr 的顺序即使它在容器中过期,也会保持不变。

关于c++ - 在 std::set 或 std::map 的键中使用 weak_ptr 是否安全,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23210092/

相关文章:

c++ - 为什么 std::weak_ptr 没有 operator->?

C++ 找到尽可能接近给定 xy 的 n 个点

c++ - 为什么 G++ 编译器不以相同的方式处理这两个函数?

c++ - 成员 init 的默认构造函数?

c++ - c++套接字io客户端无法读取使用来自另一个客户端的广播从节点服务器发送的数据

c++ - 绑定(bind)到一个weak_ptr

c++ - 奇怪的错误。在循环中使用 rand() 和数组

c++ - 来自 ExpandEnvironmentStrings 的本地化值

c++ - 在 C++ 中使用枚举类值调用数组元素

c++ - 使用指针线程化共享模型