按值捕获复制外部变量,lambda内修改不影响原变量;按引用捕获共享同一变量,修改直接影响原值,但需确保变量生命周期长于lambda。

在C++中,lambda表达式提供了一种简洁的方式来定义匿名函数。捕获列表是lambda表达式的重要组成部分,它决定了lambda如何访问外部作用域中的变量。理解按值捕获和按引用捕获的区别,对正确使用lambda至关重要。
捕获列表的基本语法
lambda表达式的完整形式如下:
[捕获列表](参数列表) -> 返回类型 { 函数体 }其中捕获列表位于方括号[]内,用于指定lambda需要使用的外部变量及其捕获方式。常见的形式包括:
- []:不捕获任何变量
- [=]:按值捕获所有外部变量
- [&]:按引用捕获所有外部变量
- [x, &y]:x按值捕获,y按引用捕获
- [this]:捕获当前对象的this指针
按值捕获(=)
按值捕获会将外部变量的副本保存到lambda内部。这意味着lambda内部的操作不会影响原始变量,且即使原始变量生命周期结束,lambda仍可安全使用其副本(前提是lambda本身未超出作用域)。
立即学习“C++免费学习笔记(深入)”;
示例:
int x = 10;auto lambda = [x]() { return x; };
x = 20;
// lambda() 返回 10,因为捕获的是初始值的副本
注意:按值捕获在lambda创建时完成,之后修改原变量不影响lambda内的值。
按引用捕获(&)
按引用捕获使lambda直接引用外部变量。lambda内部对变量的修改会影响原始变量,但必须确保lambda调用时原始变量仍然有效,否则会导致未定义行为。
示例:
int x = 10;auto lambda = [&x]() { x = 100; };
lambda();
// 此时x的值变为100
常见陷阱:如果lambda捕获了局部变量的引用,而该lambda在局部变量销毁后被调用,程序行为未定义。
混合捕获与特殊写法
可以同时使用多种捕获方式。例如:
int a = 1, b = 2;auto lambda = [a, &b]() {
a++; // 修改副本,不影响外部a
b++; // 修改外部b
};
lambda(); // a仍为1,b变为3
C++14起支持广义捕获(初始化捕获),可以在捕获列表中创建新变量:
int x = 10;auto lambda = [p = &x]() { return *p; }; // 捕获x的地址
这种写法允许更灵活的数据封装。
基本上就这些。掌握按值和按引用捕获的区别,能帮助你写出更安全、高效的lambda表达式。关键是根据变量生命周期和是否需要修改原值来选择合适的捕获方式。











