在 C++ 的 Lambda 表达式中,捕获列表([]
中的内容)决定了 Lambda 对外部变量的访问方式。this
、=
和 &
是捕获列表中常见的方式,它们的区别如下:
1. [this]
- 捕获当前对象的指针(即
this
指针)。 - 可以在 Lambda 中访问当前对象的成员变量和成员函数。
- 使用方式:
1
2
3
4[this]() {
this->memberFunction(); // 访问当前对象的成员
int value = this->memberVariable;
} - 注意事项:
- 捕获的是
this
指针,所以 Lambda 捕获的是对象本身,而不是某个具体的成员变量。 - 如果对象已经被销毁,再访问捕获的
this
会导致未定义行为。
- 捕获的是
2. [=]
按值捕获所有外部变量。
Lambda 表达式会拷贝所有使用到的外部变量的值。
适合外部变量只读的场景,因为按值捕获的变量默认是只读的。
使用方式:
1
2
3
4
5int a = 10;
[=]() {
// 捕获 a 的副本,a 是只读的
std::cout << a << std::endl;
};修改捕获变量的值:
如果想修改按值捕获的变量,可以加上mutable
修饰符:1
2
3
4
5int a = 10;
[=]() mutable {
a += 5; // 修改 a 的副本,不会影响原始变量
std::cout << a << std::endl;
};注意事项:
this
指针也会被按值捕获,因此可以访问当前对象的成员变量和成员函数。
3. [&]
按引用捕获所有外部变量。
捕获外部变量的引用,允许在 Lambda 中修改原始变量。
使用方式:
1
2
3
4
5int a = 10;
[&]() {
a += 5; // 修改的是外部变量 a
std::cout << a << std::endl;
};注意事项:
- 确保引用的变量在 Lambda 执行期间仍然有效,否则会出现未定义行为。
4. 组合使用([this, =, &]
的变种)
可以结合捕获方式,捕获所需的变量:
[this, a]
:捕获this
指针,并按值捕获变量a
。[&this]
(C++20 引入):按引用捕获this
指针。[=, &b]
:按值捕获所有外部变量,但按引用捕获变量b
。[&, a]
:按引用捕获所有变量,但按值捕获变量a
。
总结对比
捕获列表 | 捕获方式 | 使用场景 |
---|---|---|
[this] |
捕获当前对象指针 | 在 Lambda 中访问当前对象的成员 |
[=] |
按值捕获所有变量 | 外部变量只读,或者按值捕获副本操作 |
[&] |
按引用捕获所有变量 | 需要在 Lambda 中修改外部变量 |
[this, =] |
捕获当前对象和按值捕获 | 需要访问 this 和按值捕获变量 |
[=, &var] |
按值捕获,部分按引用捕获 | 默认按值,但允许修改特定变量 |
根据具体需求选择合适的捕获方式可以确保代码高效且安全。