今天有很多关于 std::weak_ptr
和 std::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)
, twoshared_ptr
orweak_ptr
instances are equivalent if and only if they share ownership or are both empty.
两种情况是
- 它们共享同一个对象,这实际上意味着它们共享同一个引用计数对象。
- 它们都是空的。
现在,我认为困惑是在第二个任期。关键是标准中的“空”意味着 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 toT*
.Effects: If
r
is empty, constructs an emptyweak_ptr
object; otherwise, constructs aweak_ptr
object that shares ownership withr
and stores a copy of the pointer stored inr
.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_ptr
由 shared_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/