我正在学习std::set。下面是我的代码:
#include <set>
#include <iostream>
using namespace std;
struct cmp{
bool operator () (const int & a,const int & b) const {
if(abs(a-b)<=3)
return false;
return a < b;
}
};
set<int,cmp> q{1, 2, 10};
int main(){
if(q.find(4)!=q.end())
cout << 1;
else
cout << 2;
}
产量:1
我使用structcmp自定义元素的排序规则,如果abs(a-b)〈=3,新元素将被删除。
但是让我吃惊的是q.find()被修改了。
我想知道为什么输出是1,q中没有4。
find(4)是要得到一个迭代器,其中q中的元素等于4,对吗?
1条答案
按热度按时间a9wyjsp71#
您似乎希望
set
使用比较器来检查两个元素是否相等(编辑:在第二次读取时,实际上不是,您没有检查是否相等,但这对答案没有太大影响)。不是这样的。set
不关心是否相等。当考虑整数和
cmp == std::less
的简单情况,那么这就是对于整数,当
a == b
时,只能是true
。然而,一般来说,等价并不等于相等。在任何情况下,当两个元素可以被认为等价时,不应该是cmp
返回true
。当两个元素排序时,当a
在b
之前时,cmp(a,b)
应该是true
。只有当
cmp
实现严格的弱排序时,这才能一致地工作,正如您在这里看到的:https://en.cppreference.com/w/cpp/named_req/Compare您的代码具有未定义的行为,因为您的比较器不满足该要求。它没有实现严格的弱排序。
也没有明显的方法来解决这个问题,因为您比较两个元素的方法不能用来对它们进行排序。
但是
这是不一致的。草率地说,如果两个元素是等价的,那么在排序时如何排列它们并不重要。1和3如何相对于彼此排列并不重要,你可以在不破坏顺序的情况下交换它们。3和5也是如此。但是顺序对1和5很重要。这是不一致的。形式上,它打破了严格弱序的最后一个要求,正如塞巴斯蒂安Redl在评论中所指出的。