C++带自定义比较器的map运行结果不符合预期问题咨询
问题原因
这是你对std::map比较器的等价判定逻辑理解有误,不属于C++的机制bug。
std::map作为有序关联容器,不会用==运算符判断两个键是否重复,它判定两个键a、b等价(即视为同一个键)的唯一规则是:
传入的比较器
comp同时满足comp(a,b) == false且comp(b,a) == false,也就是两个值在比较规则下互相都不“小于”对方,就会被判定为同一个键。
回到你写的比较器:
struct Comp { const bool operator()(const int x, const int y) const { return abs(x) < abs(y); } };
这个比较器只对比两个数的绝对值:
- 对
2和-2来说,abs(2) < abs(-2)为假,abs(-2) < abs(2)也为假,二者会被判定为等价键 - 对
4和-4来说,同理也会被判定为等价键
这就解释了你的运行结果:
插入数组{4, -2, 2, -4}时,第一个插入的同绝对值键会被保留为map的键,后续同绝对值的元素不会新增键,只会对已有键的计数做累加:
- 插入4:新增键4,计数为1
- 插入-2:绝对值2小于4,新增键-2,计数为1
- 插入2:和-2判定为等价,-2的计数累加为2
- 插入-4:和4判定为等价,4的计数累加为2
最终输出自然就是-2 -> 2、4 -> 2。
修正方案
如果你希望-4、-2、2、4都作为独立键存在,只需要修改比较器,保证四个值两两之间都不会触发等价判定即可。
如果你的预期输出顺序是按整数本身升序排列(即你给出的-4 -> 1、-2 -> 1、2 -> 1、4 -> 1顺序),直接使用map默认的less<int>比较器即可,不需要自定义比较器。
如果你需要先按绝对值升序排列、绝对值相同时再按数值升序排列,可以使用如下比较器:
struct Comp { bool operator()(int x, int y) const { if (abs(x) != abs(y)) { return abs(x) < abs(y); } // 绝对值相等时,数值更小的排在前面,区分正负值 return x < y; } };
替换后四个元素会各自作为独立键存在,计数均为1。
内容的提问来源于stack exchange,提问作者leo
相关产品推荐
相关产品推荐

