如何解决为什么对于包含自定义对象的STL集而不是operator ==,operator <重载是必要的
我正在使用C ++ 11,并且我想使用set
存储我的自定义对象,因为我需要一个容器,该容器可以过滤具有相同值的元素。
这是我的自定义对象的类:
struct Ele
{
int a,b,c;
}
据我了解,我需要重载函数operator==
,因为set
需要过滤具有相同值的元素。
但是,在阅读以下链接:How do i insert objects into STL set之后,似乎我需要重载operator<
而不是operator==
。
所以我这样编码:
struct Ele {
int a,c;
friend bool operator<(const Ele &e1,const Ele &e2);
};
bool operator<(const Ele &e1,const Ele &e2)
{
if (e1.a < e2.a) {
return true;
}
if (e1.a == e2.a) {
if (e1.b < e2.b) {
return true;
}
if (e1.b == e2.b) {
if (e1.c < e2.c) {
return true;
}
return false;
}
return false;
}
return false;
}
并进行如下测试:
set<Ele> myset;
Ele e1;
e1.a = 1;
e1.b = 2;
e1.c = 3;
Ele e2;
e2.a = 1;
e2.b = 2;
e2.c = 3;
myset.insert(e1);
myset.insert(e2);
cout << myset.size() << endl;
好吧,输出是1
,而不是2
,这意味着e2
的插入失败了,因为e2
的值与值e1
。
现在我很困惑。
据我了解,operator<
只是告诉编译器如何理解e1 < e2
,编译器如何知道如何理解e1 == e2
?如果我要设置这样的规则:e1 == e2
仅在e1.a == e2.b && e1.b == e2.c && e1.c == e2.a
时怎么办?
解决方法
==
本身不足以定义顺序,而<
足以定义顺序。此外,所有其他关系运算符都可以用operator<
进行强制转换,只要允许您对结果求反即可。
例如,如果a == b
和!(a < b)
是!(b < a)
<
是自然的选择,因为认为事物按升序排列是自然的。 >
本来可以被选中,但它并非那么容易处理。
operator<
是必需的,因为标准内部隐式要求std::map
是树状的数据结构,需要在元素之间进行某种排序。注意,仅使用operator<
就可以生成所有比较函数。看看:
a == b <==> !(a < b) && !(b < a)
a > b <==> b < a
a >= b <==> !(a < b)
以此类推
,您可以使用==
(和!
)确保唯一性,但效率不如使用<
(std::set
)或哈希函数(std::unordered_set
)。
考虑插入。仅使用==
,您将不得不比较每个元素以验证您是否还没有相等的元素。 std::set
的元素保持顺序,因此insert进行二进制搜索,查找的元素要少得多。 std::unordered_set
的元素基于哈希值保存在存储桶中,因此查找只需要搜索存储桶,而不必搜索整个集合。
如Bathsheba's回答中所述,您可以从<
合成等式函数
其他答案已经指出,std::set
要求元素的排序,这要求为类型定义operator<
。如果您不关心顺序,只关心唯一性,则可以使用std::unordered_set
。
此外,这是实现比较的一种更简洁的方法:
bool operator<(const Ele &e1,const Ele &e2)
{
return std::tie(e1.a,e1.b,e1.c) < std::tie(e2.a,e2.b,e2.c);
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。