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 等 |