简体   繁体   English

为什么 operator< 包含自定义对象的 STL 集需要重载,而不是 operator==

[英]Why is operator< overloading necessary for STL set containing custom objects, instead of operator==

I'm working with C++11 and I want to use set to store my custom objects because I need a container, which can filter the elements with the same value.我正在使用 C++11,我想使用set来存储我的自定义对象,因为我需要一个容器,它可以过滤具有相同值的元素。

Here is the class of my custom object:这是我的自定义对象的类:

struct Ele
{
    int a, b, c;
}

As my understanding, I need to overload the function operator== because set need to filter the elements with the same value.据我了解,我需要重载函数operator==因为set需要过滤具有相同值的元素。

However, after reading this link: How do i insert objects into STL set , it seems that overloading operator< is what I need, instead of operator== .但是,在阅读此链接后: How do i insert objects into STL set ,似乎重载operator<是我需要的,而不是operator==

So I code like this:所以我这样编码:

struct Ele {
    int a, b, 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;
}

And do a test as below:并进行如下测试:

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;

Well, the output is 1 , instead of 2 , which means that the insertion for e2 failed as expected because the value of e2 is the same with the value of e1 .嗯,输出是1 ,而不是2 ,这意味着e2的插入按预期失败,因为e2的值与e1的值相同。

Now I'm confused.现在我很困惑。

As my understanding, operator< just told the compiler how to understand e1 < e2 , how does compiler know how to understand e1 == e2 ?根据我的理解, operator<只是告诉编译器如何理解e1 < e2 ,编译器如何知道如何理解e1 == e2 What if I want to set such a rule: e1 == e2 only if e1.a == e2.b && e1.b == e2.c && e1.c == e2.a ?如果我想设置这样的规则: e1 == e2 only if e1.a == e2.b && e1.b == e2.c && e1.c == e2.a怎么e1.a == e2.b && e1.b == e2.c && e1.c == e2.a

== is not sufficient on its own to define an ordering, whereas < is. ==本身不足以定义排序,而<是。 Furthermore all other relational operators can be cast in terms of operator< , so long as you are allowed to negate the result.此外,所有其他关系运算符都可以根据operator< ,只要您可以否定结果。

For example, a == b if !(a < b) and !(b < a)例如, a == b if !(a < b) and !(b < a)

< is a natural choice insofar that thinking of things being in ascending order is natural. <是一个自然的选择,因为认为事物按升序排列是很自然的。 > could have been picked, but it wouldn't have been so tractable. >可以被选中,但它不会那么容易处理。

operator< is required because std::map internally is implicitly required by the standard to be a tree-like data structure that requires some kind ordering between elements. operator<是必需的,因为std::map内部隐式要求std::map是一个树状数据结构,需要元素之间的某种排序。 Notice that one can generate all the comparing functions using just operator< .请注意,只需使用operator<即可生成所有比较函数。 Take a look:看一看:

a == b <==> !(a < b) && !(b < a)
a > b <==> b < a
a >= b <==> !(a < b)

and so on等等

You could ensure uniqueness with == (and ! ), but it would be less efficient than using < ( std::set ) or a hash function ( std::unordered_set ).可以使用== (和! )确保唯一性,但它的效率会低于使用<std::set )或散列函数( std::unordered_set )。

Consider insert.考虑插入。 With only == you would have to compare every element to verify that you don't have an equal element already.只有==您必须比较每个元素以验证您已经没有相等的元素。 std::set 's elements are kept in order, so insert does a binary search, looking at far fewer elements. std::set的元素按顺序排列,因此 insert 进行二分搜索,查看的元素要少得多。 std::unordered_set 's elements are kept in buckets based on the hash value, so lookup only has to search the bucket, not the whole collection. std::unordered_set的元素根据哈希值保存在桶中,因此查找只需搜索桶,而不是整个集合。

As noted in Bathsheba's answer, you can synthesize an equality function from <正如在Bathsheba 的回答中所指出,您可以从<

The other answers already point out that std::set requires an ordering of the elements which requires operator< to be defined for the type.其他答案已经指出std::set需要对需要为类型定义operator<的元素进行排序 If you don't care about ordering, and only care about uniqueness, you can use std::unordered_set .如果你不关心排序,只关心唯一性,你可以使用std::unordered_set

Also, here's a much cleaner way to implement the comparison:此外,这是实现比较的更简洁的方法:

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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM