lambda 表达式
C++ 的 lambda 表达式 是一种轻量、内联的函数对象写法,广泛用于标准算法、自定义回调、事件响应等场景。它简洁且强大。以下将系统、详细地讲解 lambda 的语法、捕获规则、应用技巧和实际使用场景。
🧠 一、基本语法
[捕获列表](参数列表) -> 返回类型 { 函数体 }; 
示例:
auto add = [](int a, int b) -> int { return a + b; }; std::cout << add(2, 3); // 输出:5 
🧩 二、捕获列表详解
捕获列表([])用于访问外部变量。可以按值、按引用捕获,也可以使用默认捕获。
捕获方式对比:
| 写法 | 含义 | 示例变量是否可修改? | 示例 | 
|---|---|---|---|
| [] | 不捕获 | 否 | [](){} | 
| [=] | 按值捕获所有外部变量 | 否(默认) | [=]() { return x + y; } | 
| [&] | 按引用捕获所有外部变量 | 是 | [&]() { x += 1; } | 
| [x] | 按值捕获指定变量 | 否 | [x]() { return x; } | 
| [&x] | 按引用捕获指定变量 | 是 | [&x]() { x++; } | 
| [=, &y] | 默认按值, y按引用 | 混合 | [=, &y]() { y += x; } | 
| [&, x] | 默认引用, x按值 | 混合 | [&, x]() { z += x; } | 
⚠ 注意:
-  按值捕获的变量在 lambda 定义时被拷贝(或移动),后续外部变量改变不影响 lambda。 
-  要在 lambda 中修改按值捕获的变量,需加上 mutable:[x]() mutable { x++; } // 修改的是 lambda 内部的拷贝
🔧 三、参数列表与返回类型
[](int a, int b) -> int { return a + b; } 
-  参数列表可省略,适用于无参 lambda: [] { return 42; }
-  返回类型可省略,C++ 会自动推导(从 return表达式)
-  若 return有多个分支(如 if/else),需要显式指定返回类型
🎯 四、常见用法
1. 在 std::sort 中排序
 
std::vector<int> v = {3, 1, 4}; std::sort(v.begin(), v.end(), [](int a, int b) { return a < b; }); 
2. 与 STL 算法结合
std::vector<int> v = {1, 2, 3, 4}; auto it = std::find_if(v.begin(), v.end(), [](int x) { return x > 2; }); 
3. 与 for_each 连用
 
std::for_each(v.begin(), v.end(), [](int x) { std::cout << x << " "; }); 
4. 可修改外部变量(引用捕获)
int sum = 0; std::for_each(v.begin(), v.end(), [&sum](int x) { sum += x; }); 
5. 返回 lambda 并使用
auto make_adder = [](int x) { return [x](int y) { return x + y; }; }; auto add5 = make_adder(5); std::cout << add5(3); // 输出:8 
🛠 五、高级技巧
1. 使用 mutable 修改按值捕获变量
 
int x = 10; auto f = [x]() mutable { x += 5; // 修改的是 x 的副本 std::cout << x; }; f(); // 输出 15;原始 x 不变 
2. 带状态的闭包
auto counter = [i = 0]() mutable { return ++i; }; std::cout << counter(); // 1 std::cout << counter(); // 2 
3. Lambda 与函数指针转换
auto f = [](int x) { return x * 2; }; int (*fp)(int) = f; // 仅限于不捕获的 lambda(无状态) 
4. 递归 lambda(C++14 起)
std::function<int(int)> fib = [&](int n) { return (n <= 1) ? 1 : fib(n - 1) + fib(n - 2); }; 
🧪 六、lambda 捕获的实质(闭包对象)
Lambda 表达式是编译器自动生成的匿名类对象,包含:
-  成员变量(捕获的变量) 
-  重载的 operator()方法(函数体)
int a = 5; auto f = [a](int x) { return x + a; }; 
编译器会生成类似:
struct __Lambda { int a; __Lambda(int a_) : a(a_) {} int operator()(int x) const { return x + a; } }; 
✅ 总结
| 特性 | 说明 | 
|---|---|
| [] | 捕获外部变量(值/引用/混合) | 
| () | 定义参数列表 | 
| mutable | 允许修改值捕获的副本 | 
| -> type | 指定返回类型(可省略) | 
| 可嵌套/递归 | 支持 | 
| 与 STL 高度集成 | sort,for_each,find_if等 | 
