Lambda 捕获方式
一、Lambda 捕获列表的几种捕获方式
-
值捕获(by value)
捕获外部变量的当前值,lambda 内部保存的是变量的副本。
语法示例:int x = 10;auto f = [x]() { return x + 1; };
-
引用捕获(by reference)
捕获变量的引用,lambda 内部直接访问外部变量本体。
语法示例:int x = 10;auto f = [&x]() { x++; };
-
隐式捕获
[=]
:隐式按值捕获所有用到的外部变量[&]
:隐式按引用捕获所有用到的外部变量
-
混合捕获
可以在捕获列表中混合指定,比如:int x = 1, y = 2;auto f = [x, &y]() { return x + y; };
-
移动捕获(C++14 起)
使用初始化捕获将变量移动进 lambda,语法:std::unique_ptr<int> p = std::make_unique<int>(10);auto f = [ptr = std::move(p)]() { return *ptr; };
二、引用捕获需要注意什么?
-
生命周期风险
- 捕获的是外部变量的引用,如果外部变量在 lambda 调用时已经销毁,引用变成悬空,访问会导致未定义行为。
- 例如捕获局部变量的引用,但 lambda 在变量作用域外执行(如异步调用或延迟执行),就会出错。
-
修改外部变量
-
引用捕获允许修改外部变量(前提变量非
const
)。 -
例如:
int x = 10;auto f = [&x]() { x = 20; };f();std::cout << x; // 输出 20
-
-
线程安全问题
- 引用捕获多个线程访问时,可能存在数据竞争,需要同步保护。
-
不能捕获临时对象的引用
- 引用捕获不能捕获即将销毁的临时变量引用。
三、总结
[x]
[&x]
[=]
[&]