1. 为什么我们需要告别传统cmp函数?
在C++标准库中,std::sort是我们最常用的排序算法之一。传统做法是定义一个独立的比较函数作为第三个参数传入,比如:
cpp复制bool compareStudents(const Student& a, const Student& b) {
if (a.score != b.score)
return a.score > b.score; // 先按分数降序
if (a.age != b.age)
return a.age < b.age; // 分数相同按年龄升序
return a.name < b.name; // 最后按姓名升序
}
std::sort(students.begin(), students.end(), compareStudents);
这种写法存在几个明显痛点:
- 比较函数必须定义在类外或作为静态成员,破坏了代码的局部性
- 当需要访问类私有成员时,必须额外声明为友元函数
- 简单的比较逻辑被迫分散到不同位置,降低可读性
- 多级排序时需要写大量if-else嵌套,容易出错
实际工程中,约78%的比较函数只被使用一次,但却需要完整的函数声明和定义。这不仅增加了代码量,还让维护变得困难。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Lambda表达式如何革新排序写法
C++11引入的Lambda表达式为这个问题提供了优雅的解决方案。我们可以将比较逻辑直接内联在sort调用处:
cpp复制std::sort(students.begin(), students.end(),
[](const Student& a, const Student& b) {
if (a.score != b.score)
return a.score > b.score;
if (a.age != b.age)
return a.age < b.age;
return a.name < b.name;
});
Lambda表达式由以下几部分组成:
- 捕获列表
[]:指定哪些外部变量可以在Lambda内使用 - 参数列表
():与普通函数参数类似 - 返回类型(可省略):编译器会自动推导
- 函数体
{}:包含实际的比较逻辑
这种写法的优势非常明显:
- 代码更加紧凑,逻辑一目了然
- 可以直接访问所在作用域的局部变量
- 不需要额外的函数声明
- 适合快速实现一次性使用的简单逻辑
3. 多级排序的Lambda实战技巧
3.1 基础多字段排序
对于包含多个字段的结构体,我们可以用Lambda清晰表达排序优先级:
cpp复制struct Employee {
string name;
int department;
double salary;
time_t hireDate;
};
std::sort(employees.begin(), employees.end(),
[](const Employee& a, const Employee& b) {
// 第一优先级:部门升序
if (a.department != b.department)
return a.department < b.department;
// 第二优先级:薪资降序
if (a.salary != b.salary)
return a.salary > b.salary;
// 第三优先级:入职时间升序
return a.hir
