我在地图中使用弱指针作为键。然而,当我尝试编译时,我得到了丑陋的消息,我解释为我缺少std :: weak_ptr的比较运算符,显然,它在std :: map中是必需的,因为它根据它对其元素进行排序关键价值。
然而,现在,weak_ptr类是一个智能指针类型类,因此可以使用指向某些托管数据的指针。
这个类是否有充分的理由不提供运算符的基本实现<方法 ?我的意思是,比较指针值对我来说似乎很明显,并且,如果要求它以不同的方式工作,那么应该能够扩展或重新定义该方法,以获得预期的行为,而不是是吗?
这里非常感谢您的见解。 感谢您的期待。
答案 0 :(得分:11)
更新:有一种定义明确的方式来比较std::weak_ptr
,请参阅@ Richard的回答。我会留下我的答案用于历史档案目的。
实施好operator<
需要从shared_ptr
创建weak_ptr
并调用其operator<
。这是
shared_ptr
不再存在时,一般来说,很难获得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()
并检查返回值是否为空。