虽然我理解为什么operator==
和shared_ptr
没有unique_ptr
,但我想知道为什么shared_ptr
和weak_ptr
没有weak_ptr
。特别是因为您可以通过shared_ptr
上的引用创建lhs.get() == rhs.get()
。
我认为99%的时间你想要{{1}}。我现在要继续向我的代码介绍,除非有人能给我一个充分的理由,为什么不应该做这样的事情。
答案 0 :(得分:16)
weak_ptr
没有get()
方法,因为您需要在访问基础指针之前显式锁定weak_ptr
。明确这一点是一个深思熟虑的设计决策。如果转换是隐式的,那么在编写从shared_ptr
获取的基础指针仍然被检查的同时,如果要销毁对象的最后weak_ptr
,那么编写将是不安全的代码将非常容易。 / p>
This boost page很好地描述了陷阱以及为什么weak_ptr
具有如此有限的界面。
如果您需要进行快速比较,那么您可以执行shared == weak.lock()
。如果比较结果为真,那么您知道weak
必须仍然有效,因为您对同一个对象保持单独的shared_ptr
。如果比较返回false,则没有这样的保证。
答案 1 :(得分:4)
因为它有成本。
weak_ptr
就像一个观察者,而不是真正的指针。要使用它进行任何工作,首先需要使用shared_ptr
方法从中获取lock()
。
这具有获得所有权的效果,但它与复制常规shared_ptr
(计数增量等等)一样昂贵,因此这不是一件轻而易举的事。
因此,如果不提供==
,您将被迫退回并实际检查您是否真的需要这样做。
答案 2 :(得分:3)
正如其他答案所指出的那样,仅比较底层指针将是危险的。对于其中一个,请考虑以下情形:对对象存在弱引用A,该对象随后被删除,因此弱引用到期。然后,在所述删除所释放的存储器中分配另一个对象,该对象具有相同的地址。现在,即使弱指针最初指向另一个对象,底层指针也相同!
正如其他答案所建议的那样,一种方法是比较shared == weak.lock()
。由于如果弱指针过期,lock()
将返回nullptr
(而不是伪造的指针),因此他的工作是确定它们是否相等(只要shared != nullptr
)。但是,这有两个问题:
shared == nullptr
时返回true。如果比较必须保持稳定,例如在unordered_map
或unordered_set
中用作比较键时,这可能很危险。lock()
是一个相对昂贵的操作。幸运的是,有更好的方法可以做到这一点。 weak_ptr
和shared_ptr
都还存储了一个指向控制块的指针,该存储块存储了引用计数,并且只要保留了引用,该生存期就会超过原始对象对此。要检查它们是否引用相同的对象,我们要做的就是比较控制块指针。这可以通过owner_before
方法完成:
template<class T>
bool owner_equals(std::shared_ptr<T> &lhs, std::weak_ptr<T> &rhs) {
return !lhs.owner_before(rhs) && !rhs.owner_before(lhs);
}
如果您想知道两个std::weak_ptr
是否(一次)引用同一对象,则此方法甚至可以用于相互比较,因为控制块将持续(至少)个时间。所有弱引用。
请记住,如果您使用std::shared_ptr
的别名功能,这可能不会产生预期的结果,该功能使您可以使用相同的控制块创建两个std::shared_ptr
实例。尽管如此,存储不同的指针。