C++ 的 lambda 表达式是一种匿名函数对象,可以在代码中直接定义和使用。它们特别适用于需要传递函数作为参数的场景,例如在算法中使用自定义比较函数,或者在异步编程中传递任务。以下是对 lambda 表达式的详细解释:
1. 基本语法
cpp
[捕获列表](参数列表) -> 返回类型 {
// 函数体
}
捕获列表
- 值捕获 :
[x]
将变量x
按值捕获。 - 引用捕获 :
[&x]
将变量x
按引用捕获。 - 隐式捕获 :
[=]
捕获所有外部变量按值,[&]
捕获所有外部变量按引用。 - 混合捕获 :
[this, &x]
同时捕获this
指针和变量x
的引用。
参数列表
- 类似普通函数的参数列表,可以为空。
返回类型
- 可以省略,编译器会自动推断。
- 如果函数体中有多个
return
语句,并且返回类型不同,编译器可能会报错。
函数体
- 包含函数的逻辑。
2. 示例代码
cpp
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
// 定义一个简单的 lambda 表达式
auto add = [](int a, int b) -> int {
return a + b;
};
std::cout << "1 + 2 = " << add(1, 2) << std::endl;
// 捕获外部变量
int x = 10;
auto multiply = [x](int y) -> int {
return x * y;
};
std::cout << "10 * 3 = " << multiply(3) << std::endl;
// 捕获外部变量并修改
int z = 5;
auto increment = [&z]() -> void {
z++;
};
std::cout << "Before increment: " << z << std::endl;
increment();
std::cout << "After increment: " << z << std::endl;
// 在算法中使用 lambda 表达式
std::vector<int> vec = {1, 2, 3, 4, 5};
std::for_each(vec.begin(), vec.end(), [](int n) {
std::cout << n * 2 << " ";
});
return 0;
}
3. 捕获列表的详细解释
值捕获
cpp
int x = 5;
auto lambda = [x]() {
x = 10; // 修改捕获的值
};
lambda();
std::cout << x << std::endl; // 输出 5,因为 x 是按值捕获的
引用捕获
cpp
int x = 5;
auto lambda = [&x]() {
x = 10; // 修改捕获的引用
};
lambda();
std::cout << x << std::endl; // 输出 10,因为 x 是按引用捕获的
隐式捕获
cpp
int x = 5;
auto lambda = [=]() {
std::cout << x << std::endl; // 按值捕获 x
};
cpp
int x = 5;
auto lambda = [&]() {
std::cout << x << std::endl; // 按引用捕获 x
};
混合捕获
cpp
int x = 5;
int y = 10;
auto lambda = [x, &y]() {
std::cout << x << " " << y << std::endl;
y = 20; // 修改 y 的值
};
lambda();
std::cout << x << " " << y << std::endl; // 输出 5 20
4. 返回值的详细解释
自动推断返回值
cpp
auto lambda = [](int a, int b) {
return a + b; // 返回值类型推断为 int
};
显式指定返回值
cpp
auto lambda = [](int a, int b) -> int {
return a + b; // 显式指定返回值类型为 int
};
5. 高级用法
使用Lambda表达式递归
cpp
auto factorial = [](int n) -> int {
if (n <= 1) return 1;
return n * factorial(n - 1); // 错误,因为 capture-by-reference 不支持自我调用
};
// 为了支持递归,可以使用 y-combinator 或捕获自身
auto factorial = [&](int n) -> int {
if (n <= 1) return 1;
return n * factorial(n - 1);
};
使用Lambda表达式绑定成员函数
cpp
class MyClass {
public:
int value = 0;
void SetValue(int v) {
value = v;
}
};
MyClass obj;
auto lambda = [obj]() {
obj.SetValue(10); // 调用成员函数
};
使用Lambda表达式进行完美转发
cpp
template<typename T>
auto lambda = [](T&& arg) {
func(std::forward<T>(arg)); // 完美转发
};
6. 总结
C++ 的 lambda 表达式是一种非常灵活的工具,可以简化代码并提高可读性。通过捕获列表,lambda 表达式可以在不同的作用域中访问变量,并且可以通过值或引用的方式捕获这些变量。通过显式指定返回值类型,也可以更精确地控制函数行为。