为什么没有运营商<对于类std :: weak_ptr?

时间:2018-04-09 12:14:13

标签: c++ c++-standard-library

我在地图中使用弱指针作为键。然而,当我尝试编译时,我得到了丑陋的消息,我解释为我缺少std :: weak_ptr的比较运算符,显然,它在std :: map中是必需的,因为它根据它对其元素进行排序关键价值。

然而,现在,weak_ptr类是一个智能指针类型类,因此可以使用指向某些托管数据的指针。

这个类是否有充分的理由不提供运算符的基本实现<方法 ?我的意思是,比较指针值对我来说似乎很明显,并且,如果要求它以不同的方式工作,那么应该能够扩展或重新定义该方法,以获得预期的行为,而不是是吗?

这里非常感谢您的见解。 感谢您的期待。

3 个答案:

答案 0 :(得分:11)

更新:有一种定义明确的方式来比较std::weak_ptr,请参阅@ Richard的回答。我会留下我的答案用于历史档案目的。

实施好operator<需要从shared_ptr创建weak_ptr并调用其operator<。这是

  1. a&#34;昂贵的&#34;操作
  2. 当基础shared_ptr不再存在时,
  3. 未定义。
  4. 一般来说,很难获得weak_ptr的明确定义和高效的排序。

    请注意,您始终可以将自定义比较器传递给地图对象,您可以按照您想要的任何方式实现该比较器,并仅保留本地对象。但是,由您来决定一个很好的方法来做到这一点。也许您可以使用指向连接shared_ptr的控制块的指针,但这是您无法访问的实现细节。所以我真的没有看到这样做的有意义的方式。

答案 1 :(得分:9)

std::owner_less是将智能指针作为地图中的键进行排序的正确方法。

#include <map>
#include <memory>
#include <string>

struct Foo
{
};

using my_key = std::weak_ptr<Foo>;
using my_comp = std::owner_less<my_key>;

int main()
{
    auto m = std::map<my_key, std::string, my_comp>();

    auto p = std::make_shared<Foo>();
    auto p1 = std::make_shared<Foo>();

    m.emplace(p, "foo");
    m.emplace(p1, "bar");

    p.reset();
    p1.reset();
}

答案 2 :(得分:1)

我认为关键点在于(引自column(),第194页,强调我的)

  

使用这样的危险指针依赖于这样一个事实,即在它引用的对象被删除之后使用指针的值是安全的。 如果您使用new和delete 的默认实现,这在技术上是未定义的行为,因此您需要确保您的实现允许它,或者您需要使用允许此类使用的自定义分配器。 / p>

提供operator<()需要读取原始指针值,这可能导致未定义的行为(即,当expired()返回true时)。实际上没有办法保证比较没问题,除非你先lock()并检查返回值是否为空。