C++的lambda表达式是可以在函数内部定义的匿名函数对象,捕获列表位于lambda参数列表之前,用于指定lambda函数体可以访问的外部变量以及访问方式。捕获列表的存在让lambda可以灵活使用上下文中的变量,是实现闭包特性的关键。

lambda表达式基本语法
lambda表达式的基本结构如下,其中捕获列表是可选部分,但如果需要访问外部变量则必须正确配置。
// 基本语法结构
[捕获列表](参数列表) mutable(可选) 异常属性(可选) -> 返回类型(可选) {
// 函数体
}
值捕获
值捕获会在lambda表达式定义时,将外部变量的副本保存到lambda内部,之后外部变量的修改不会影响lambda内部的副本,默认情况下值捕获的变量在lambda内部是只读的。
值捕获的基本使用
#include <iostream>
using namespace std;
int main() {
int a = 10;
// 值捕获a,lambda内部保存a的副本
auto func = [a]() {
cout << "lambda内部a的值: " << a << endl;
// a = 20; // 编译错误,值捕获的变量默认不可修改
};
a = 20; // 修改外部a的值
func(); // 输出10,不受外部修改影响
cout << "外部a的值: " << a << endl;
return 0;
}
mutable关键字的作用
如果需要修改值捕获的副本,需要在lambda表达式后添加mutable关键字,此时修改的是lambda内部的副本,不会影响外部变量。
#include <iostream>
using namespace std;
int main() {
int a = 10;
// 添加mutable允许修改值捕获的副本
auto func = [a]() mutable {
a = 30;
cout << "lambda内部修改后的a: " << a << endl;
};
func();
cout << "外部a的值: " << a << endl; // 外部a仍然是10
return 0;
}
引用捕获
引用捕获会让lambda内部直接引用外部的变量,不会创建副本,外部变量的修改会同步反映到lambda内部,反之lambda内部对变量的修改也会影响外部变量。
引用捕获的基本使用
#include <iostream>
using namespace std;
int main() {
int a = 10;
// 引用捕获a,lambda内部直接引用外部a
auto func = [&a]() {
cout << "lambda内部a的值: " << a << endl;
a = 30; // 修改引用捕获的变量,会影响外部
};
func();
cout << "外部a的值: " << a << endl; // 输出30,被lambda修改了
return 0;
}
隐式捕获
除了显式指定捕获的变量,还可以使用隐式捕获让编译器自动推断需要捕获的变量,[=]表示隐式值捕获,[&]表示隐式引用捕获。
#include <iostream>
using namespace std;
int main() {
int x = 1, y = 2;
// 隐式值捕获所有用到的外部变量
auto func1 = [=]() {
cout << "x: " << x << ", y: " << y << endl;
};
// 隐式引用捕获所有用到的外部变量
auto func2 = [&]() {
x = 10;
y = 20;
};
func1();
func2();
func1(); // x和y已经被修改
return 0;
}
值捕获与引用捕获的对比
两种捕获方式的核心区别如下:
| 对比项 | 值捕获 | 引用捕获 |
|---|---|---|
| 数据存储 | 保存外部变量的副本 | 直接引用外部变量 |
| 外部修改影响 | 不影响内部副本 | 同步影响内部引用 |
| 内部修改权限 | 默认只读,加mutable可修改副本 | 可直接修改外部变量 |
| 生命周期要求 | 无特殊要求 | 需保证外部变量生命周期长于lambda |
泛型lambda
从C++14开始支持泛型lambda,即lambda的参数可以使用auto关键字,让lambda可以接受任意类型的参数,本质上泛型lambda会被编译器展开为模板函数对象。
#include <iostream>
using namespace std;
int main() {
// 泛型lambda,参数使用auto,可接受任意类型
auto generic_lambda = [](auto a, auto b) {
return a + b;
};
// 调用时可以传入不同类型参数
cout << generic_lambda(1, 2) << endl; // 整数相加
cout << generic_lambda(1.5, 2.3) << endl; // 浮点数相加
cout << generic_lambda(string("hello"), string(" world")) << endl; // 字符串拼接
return 0;
}
泛型lambda可以和捕获列表结合使用,捕获外部变量后处理不同类型的输入参数,大幅提升代码的通用性。
#include <iostream>
using namespace std;
int main() {
int base = 10;
// 捕获base,泛型lambda处理不同输入类型
auto add_base = [base](auto value) {
return base + value;
};
cout << add_base(5) << endl; // 15
cout << add_base(3.2) << endl; // 13.2
return 0;
}
C++_lambda值捕获引用捕获泛型lambda修改时间:2026-06-25 16:00:24