C++ Lambda默认值捕获[=]行为不符合预期的技术咨询
关于Lambda表达式
[=]值捕获的困惑解答 我是C++编程新手,对Lambda的默认值捕获[=]感到困惑。根据文档说明,[=]应隐式按值捕获Lambda内部使用的自动变量,但以下程序显示被捕获的变量实际被修改,而非创建副本。
= (implicitly capture the used automatic variables by copy).
程序代码
#include <iostream> #include <atomic> class A { public: A() : value_{0} {} void increase() { auto inc = [=](){ value_++; }; inc(); } int value_; }; int main() { A a; std::cout << "value before: " << a.value_ << std::endl; a.increase(); std::cout << "value after: " << a.value_ << std::endl; }
程序输出
value before: 0
value after: 1
问题解析
这里的核心误区是对“自动变量”的理解:value_是类的成员变量,不是当前函数的自动变量。在非静态成员函数increase()中,直接访问value_等价于this->value_——Lambda里并没有直接捕获value_,而是捕获了this指针(按值捕获)。
[=]捕获的是当前作用域下的自动变量,这里的自动变量就是this指针本身。虽然捕获的是this的副本,但这个副本依然指向原对象的实例,所以Lambda中对value_的修改,本质是通过this指针操作原对象的成员变量,自然会改变原对象的值。
解决方案
如果想要真正按值捕获成员变量,有两种常见方式:
- 显式捕获成员变量的局部副本
void increase() { auto val_copy = value_; auto inc = [=](){ val_copy++; // 修改的是局部副本,不影响原对象的value_ }; inc(); } - 捕获整个对象的副本(C++11及以上)
void increase() { auto inc = [=, *this](){ value_++; // 修改的是对象副本的成员变量,原对象不受影响 }; inc(); }
内容的提问来源于stack exchange,提问作者Eric Sun
相关产品推荐
相关产品推荐

