C 排序比较器为什么不能写成小于等于理解严格弱序给 std::sort 传一个返回 bool 的函数还不够。比较器必须形成一致的排序规则否则算法的前提就被破坏结果并不只是“顺序偶尔不对”。最低标准C17。示例按分数降序、姓名升序排列。1. 比较器回答的是“a 是否应该排在 b 前面”#includealgorithm#includeiostream#includestring#includevectorstructStudent{std::string name;intscore;};intmain(){std::vectorStudentstudents{{Bo,90},{An,90},{Chen,80}};autobefore[](constStudenta,constStudentb){if(a.score!b.score)returna.scoreb.score;returna.nameb.name;};std::sort(students.begin(),students.end(),before);for(constautos:students)std::couts.name:s.score\n;std::coutstd::boolalphabefore(students[0],students[0])\n;}输出为 An:90、Bo:90、Chen:80最后是 false。比较同一个元素必须得到 false这也是检查比较器最容易做的一项测试。2. 严格弱序的几个核心要求不可自反comp(a, a) 必须为 false。传递性a 排在 b 前面b 排在 c 前面a 就应排在 c 前面。另外由“两边都不在对方前面”定义的等价关系也需要满足传递性。这些要求共同保证元素能被划分成有序的等价组。排序意义上的等价不一定等于 operator只比较分数时同分但不同姓名的学生也属于同一等价组。把写成会让相等元素互相声称排在对方前面直接违反要求。把两个字段的比较简单用逻辑或连接也可能在字段互相冲突时同时得到 comp(a,b) 和 comp(b,a) 为 true。3. 多字段比较要逐级决胜示例先比较分数只有分数相同时才比较姓名。若所有关键字段都相同就返回 false不需要人为制造赢家。全部字段同向升序时元组的字典序比较也是常用写法。比较器应保持稳定的规则不要在其中随机取值、修改排序关键字段或依赖不断变化的外部状态。也不要用整数相减的符号代替比较减法可能溢出。4. 浮点 NaN 要单独制定策略普通浮点小于比较遇到 NaN 时两边都可能为 false在包含 NaN 的数据域上直接拿它排序可能破坏所需的等价关系。可以先把 NaN 分成固定的一组再对正常数值比较并明确 NaN 放在开头还是结尾。小结先确认规则一致再关心排序速度。对比较器测试相同值、并列值、边界值与三元素传递关系往往比只观察一次排序输出更能发现问题。