我有std::multiset
存储class A
的元素。我为这个课提供了自己的operator<
实现。我的问题是,如果我在这个multiset中插入两个等效对象,他们的顺序是否有保证?例如,首先我将对象a1
插入到集合中,然后将等效对象a2
插入到此集合中。当我遍历集合时,我可以期望a1
在a2
之前到来吗?如果不是,有没有办法用multiset来实现这个目标?
答案 0 :(得分:21)
在C ++ 03中,我们无法保证insert
和erase
保留相对排序。但是,这在C ++ 0x中发生了变化:
n3092,§23.2.4/ 4:关联容器支持唯一键,如果每个键最多可包含一个元素。否则,它支持等效键。 set和map类支持唯一键; multiset和multimap类支持等效键。 对于multiset和multimap,insert和erase保留等效元素的相对顺序。 强调我的。
这在defect report中讨论。 This page是关于这个问题的评论集合,它写得很好并且非常充实。 (我非常建议您在之前的“概述”链接中阅读此内容。)
在该评论页面中,您将找到当前实施的比较,因此您可以检查您打算使用的实施是否符合您的预期。
我想不出一种强迫你想要的排序的方法。 :/
答案 1 :(得分:3)
考虑到a1
和a2
在您的示例中比较相等,std::multiset
中实际存储的内容是a1
和{{1}的副本我真的不知道你怎么知道哪个是哪个。
如果你能说出不同之处,那么a2
可能并非设计得很好。所以class A
并不保证这样的事情。
答案 2 :(得分:1)
std :: multimap不保证这一点。
如果您可以通过函数使用整数来表达operator<
,例如int A::orderingInt()
,您可以使用
std::multiset<MyCustom> myset;
与
class MyCustom : public std::vector<A> {}
重载
bool operator<(const MyCustom& a, const MyCustom& b) {
// theoretically empty MyCustom should not occure
return a[0].orderingInt() < b[0].orderingInt();
}
当然,添加和迭代现在会有所不同:
A a;
myset[a.orderingInt()].push_back(a);
// groups with "small" elements first
for(std::multiset<MyCustom>::iterator it=myset.begin(); it!=myset.end(); it++) {
// those elements are "equal"
for(std::vector<A>::iterator jt=it->begin(); jt->end(); jt++) {
// use A& a = *jt;
}
}