C++中set比较器与仿函数协同工作及去重逻辑解析
为什么仅实现小于比较的仿函数就能让std::set完成去重
std::set的去重逻辑从设计之初就不要求用户单独提供元素相等的判断逻辑,整个插入、排序、去重流程里,根本不会主动调用元素的相等运算符,所有等价判定完全基于你传入的、只定义了小于比较的比较器推导得出,核心规则遵循C++标准对关联容器的严格弱序要求。
核心判定规则
两个元素被判定为重复(即等价)的逻辑,完全通过两次反向的小于比较推导,根本不需要额外的相等判断函数:
// comp 是你传入的比较器,既可以是默认的std::less,也可以是自定义的comparator仿函数 bool is_equivalent = !comp(element_a, element_b) && !comp(element_b, element_a);
只要两个元素满足“a不小于b,且b也不小于a”,就会被set判定为重复元素,不会重复插入。
结合示例代码的具体行为解释
你代码里两个set的size差异,完全可以用上面的规则解释:
- 使用默认比较器
std::less<int*>时,比较逻辑是直接对比两个指针本身的内存地址。两次反向比较永远会出现“一个小于另一个”的结果,不可能出现双向都不满足小于条件的情况,因此四个new出来的指针哪怕指向相同的整数值,也会被判定为独立元素,最终size为4。 - 使用自定义comparator时,比较逻辑是对比指针指向的整数值。此时两个指向1的指针互相比较时,双向都不满足小于条件,会被判定为等价重复;同理两个指向2的指针也会被判定为等价重复,最终set只会保留两个元素,size为2。
这种设计的初衷
要求关联容器仅基于小于比较推导等价关系,本质是为了减少重复实现成本:只要你能为元素定义符合严格弱序要求的小于逻辑,标准库就可以自动完成排序、查重的全部流程,不需要你额外再写一套独立的相等判断逻辑,也能避免“小于规则和相等规则不一致”带来的隐性bug。
内容的提问来源于stack exchange,提问作者teamclouday
相关产品推荐
相关产品推荐

