Lambda 表达式是 C++11 引入的匿名函数对象,用于简化代码、支持函数式编程风格,并替代传统函数对象(如仿函数)。其核心功能是在作用域内捕获变量,并定义轻量级的局部函数逻辑。
一、Lambda 表达式的基本语法
语法结构
[捕获列表] (参数列表) -> 返回类型 {
函数体
}
- 捕获列表(Capture List):指定如何从外部作用域捕获变量。
- 参数列表(Parameter List):与普通函数的参数列表一致。
- 返回类型(Return Type):可省略(编译器自动推导),复杂时需显式声明。
- 函数体(Body):执行逻辑。
示例
auto lambda = [](int a, int b) -> int {
return a + b;
};
int result = lambda(3, 4); // result = 7
二、捕获列表(Capture List)
1. 捕获方式
语法 | 行为 |
---|---|
[] |
不捕获任何外部变量。 |
[=] |
按值捕获所有外部变量(隐式捕获)。 |
[&] |
按引用捕获所有外部变量(隐式捕获)。 |
[x, &y] |
显式按值捕获 x ,按引用捕获 y (混合捕获)。 |
[this] |
捕获当前类的 this 指针,可访问成员变量和函数。 |
[*this] (C++17) |
按值捕获当前对象的副本(避免悬垂引用)。 |
2. 示例
int x = 10;
int y = 20;
// 按值捕获 x,按引用捕获 y
auto lambda = [x, &y]() {
y = x + y; // x 是副本,y 是引用
};
lambda();
// x=10(未变),y=30
3. 初始化捕获(C++14)
允许在捕获列表中初始化变量(类似闭包):
auto x = 5;
auto lambda = [y = x + 1] { return y; }; // y 初始化为 6
三、mutable
关键字
- 功能:允许在 Lambda 体内修改按值捕获的变量(默认按值捕获的变量是
const
)。 - 示例:
int x = 0; auto lambda = [x]() mutable { x++; // 允许修改 x 的副本 return x; }; lambda(); // 返回 1,但外部 x 仍为 0
四、返回类型推导
- 隐式推导:若函数体仅有一个
return
语句,编译器自动推导返回类型。 - 显式声明:复杂逻辑需显式指定返回类型:
auto lambda = [](int a, double b) -> double { if (a > 0) return a + b; else return b; };
五、泛型 Lambda(C++14)
- 功能:参数支持
auto
,使 Lambda 可接受任意类型参数。 - 示例:
auto print = [](const auto& value) { std::cout << value << "\n"; }; print(42); // int print("Hello"); // const char*
六、应用场景
1. STL 算法中的回调函数
std::vector<int> vec = {3, 1, 4, 1, 5};
std::sort(vec.begin(), vec.end(), [](int a, int b) {
return a > b; // 降序排序
});
2. 异步任务封装
#include <thread>
#include <future>
auto task = [](int x) {
return x * x;
};
std::future<int> result = std::async(std::launch::async, task, 5);
3. 事件处理(如 GUI 回调)
button.onClick([&]() {
updateUI(); // 捕获外部引用,访问 UI 组件
});
七、C++17/20 增强
1. constexpr
Lambda(C++17)
Lambda 可在编译时求值:
constexpr auto square = [](int x) { return x * x; };
static_assert(square(5) == 25, "");
2. 模板参数列表(C++20)
支持显式模板参数:
auto lambda = []<typename T>(T x) { return x; };
八、注意事项
-
悬空引用:
避免捕获局部变量的引用后,其生命周期结束(如异步任务中)。 -
this
指针捕获:
若对象已销毁,通过[this]
或[&]
访问成员会导致未定义行为。 -
性能影响:
Lambda 会生成匿名类对象,频繁捕获大对象可能影响性能。
九、总结
特性 | 说明 |
---|---|
捕获列表 | 按值/引用捕获变量,支持混合捕获和初始化捕获(C++14)。 |
mutable |
允许修改按值捕获的变量副本。 |
泛型 Lambda(C++14) | 参数支持 auto ,处理多类型。 |
constexpr (C++17) |
编译时求值。 |
应用场景 | STL 算法、异步任务、事件处理。 |
Lambda 表达式通过简洁的语法替代传统函数对象,极大提升了代码可读性和灵活性,是现代 C++ 开发的核心工具之一。