[C++]Lambda
[C++]Lambda 表达式
概述
在 C++ 开发中,我们经常需要向 STL 算法传递可调用的对象(Callable Object)。传统的方式包括:
- 函数指针
- 函数对象(Functor)
C++11 引入了 Lambda 表达式,使用 [] 代替函数名来定义匿名函数,其返回类型通常由编译器自动推断。
《C++ Primer Plus》:在C++中引入lambda的主要目的是,让您能够将类似于函数的表达式用作接受函数指针或函数符的函数的参数。因此,典型的lambda是测试表达式或比较表达式,可编写为一条返回语句。这使得lambda简洁而易于理解,且可自动推断返回类型。
为什么使用 Lambda
相比于传统的函数指针和函数对象,Lambda 表达式有以下显著优势:
- 定义位置:可以在使用的位置就地定义,代码逻辑更连贯,无需跳转到其他地方查看实现。
- 简洁性:语法紧凑,减少样板代码。
- 效率:编译器可以更容易地内联 Lambda 表达式的代码,而通过函数指针调用的函数通常很难被内联。
- 功能强大:支持捕获列表,可以灵活地访问上下文中的变量。
语法与捕获列表
Lambda 表达式以 [] 开头,这被称为引入符(introducer)。它不仅标志着 Lambda 的开始,还可以用来捕获外部变量(Closure)。
常见的捕获方式包括:
[=]:以值传递方式捕获作用域内的所有外部变量。[&]:以引用传递方式捕获作用域内的所有外部变量。[x]:仅以值传递方式捕获变量x。[&x]:仅以引用传递方式捕获变量x。
示例比较
下面的代码展示了三种方式实现学生比较逻辑的差异:
1. 准备工作
// 假设有一个 Student 类
class Student {
public:
int getId() const { return id; }
// ...
private:
int id;
};
2. 实现比较逻辑的三种方式
// 方式一:普通函数
bool compareStudents(const Student& s1, const Student& s2) {
return s1.getId() < s2.getId();
}
// 方式二:函数对象(Functor)
class StudentComparator {
public:
bool operator()(const Student& s1, const Student& s2) {
return s1.getId() < s2.getId();
}
};
// 方式三:Lambda 表达式
auto lambda = [](const Student& s1, const Student& s2) {
return s1.getId() < s2.getId();
};
3. 在 STL 算法中的调用
std::vector<Student> students;
// ... 初始化 students ...
// 使用函数指针
auto pCompare = compareStudents; // 也可以直接传入函数名
std::sort(students.begin(), students.end(), pCompare);
// 使用函数对象
StudentComparator comparator;
std::sort(students.begin(), students.end(), comparator);
// 使用 Lambda 表达式(最简洁)
std::sort(students.begin(), students.end(), [](const Student& s1, const Student& s2) {
return s1.getId() < s2.getId();
});

浙公网安备 33010602011771号