std::sort 的 cmp 参数必须是可默认构造且无状态的函数;带捕获的 lambda(如[&]{})在 C++11/14 中不可用,而不带捕获的 lambda、普通函数或 std::tie(注意降序字段取反)是正确的。

sort 的 cmp 参数必须是可调用的、无状态的函数
不是所有看起来能“传进去”的东西都能被 std::sort 接受。比如捕获局部变量的 lambda([&]{} 或 [=]{})在 C++11/14 中无法直接作为 sort 的第三个参数——因为 sort 要求比较器是 可默认构造 且 无状态 的,而带捕获的 lambda 类型不可默认构造。
常见错误现象:error: no matching function for call to 'sort',尤其在老编译器(如 GCC 4.8)或启用了 -std=c++11 但没开 -std=c++14 时更易触发。
- ✅ 正确:不带捕获的 lambda(
[ ](int a, int b) { return a > b; }),它等价于函数指针 - ✅ 正确:普通函数(
bool cmp(int a, int b) { return a ) - ✅ 正确:定义了
operator()的 struct(无成员变量,或仅含 const 静态成员) - ❌ 错误:带捕获的 lambda(
[x](int a, int b) { return a ),除非你把它包装成 <code>std::function并传给支持谓词的算法(但sort不接受std::function作模板参数)
vector> 按 second 升序、first 降序排序
这是高频使用场景:多字段排序,且方向不一致。不能靠两次 sort(后一次会打乱前一次的稳定顺序),得写一个原子比较逻辑。
关键点在于比较顺序:先比 second,相等再比 first;且 first 要“降序”,即用 b.first 而非 <code>a.first 。
立即学习“C++免费学习笔记(深入)”;
sort(v.begin(), v.end(), [](const auto& a, const auto& b) {
if (a.second != b.second) return a.second < b.second;
return a.first > b.first; // 注意这里是 >
});
- 如果用
std::tie简写,记得降序字段要取反:return std::tie(a.second, -a.first) (仅适用于整数) - 字符串字段降序?用
b.second ,别直接套 <code>std::greater——它只作用于单字段 - 性能影响:lambda 内联通常无开销;但若比较逻辑复杂(如涉及字符串查找),建议加
[[likely]]或提前剪枝
自定义结构体排序时忘记重载 operator< 或传 cmp 就报错
std::sort 对自定义类型默认依赖 operator<。没定义就编译失败,错误信息常是:invalid operands to binary expression ('MyStruct' and 'MyStruct') 或类似 template instantiation failed 提示。
不是所有 IDE 都能准确定位到缺失 operator<,尤其当结构体嵌套或用了 using 别名时。
- 最简方案:在结构体内加
bool operator<(const MyStruct& rhs) const { return id < rhs.id; } - 更灵活方案:独立写
cmp函数或 lambda,显式传给sort,避免污染结构体定义 - 注意 const 正确性:比较函数参数务必是
const T&,否则对vector<const T>或临时对象会编译失败 - 如果结构体字段多且排序逻辑变,别硬塞进
operator<——它语义上应代表“自然序”,而非某次业务需要的临时规则
用 greater<int> 时发现排序结果和预期相反
std::greater<int> 是函数对象,不是布尔值。传它给 sort 表示“用大于号做比较”,即升序变降序——但它本身不反转数组,只是改变比较逻辑。
容易踩的坑是把它和 std::reverse 混淆,或者误以为 greater 要配合 less 切换使用。
- ✅ 正确用法:
sort(v.begin(), v.end(), greater<int>());→ 降序 - ✅ 也可写成:
sort(v.begin(), v.end(), [](int a, int b) { return a > b; }); - ❌ 错误:写成
sort(v.begin(), v.end(), greater<int>)(少括号)→ 编译不过,提示类型不匹配 - ❌ 错误:对
vector<string>直接用greater<string>却没确认 locale 设置,导致中文或 emoji 排序异常(此时该用std::locale或自定义 strcmp 逻辑)
真正麻烦的是跨平台排序一致性:Windows 的 greater<wstring> 和 Linux 下行为可能不同,这时候别图省事,老老实实写明确的 lambda。










