C++ Lambda表达式变量捕获时机探究:值捕获为何正确?
Lambda变量捕获时机的疑问
下面的代码通过Lambda表达式启动线程,Lambda以引用方式捕获局部变量testVar。当线程函数执行时,该局部变量已超出作用域,导致线程无法访问正确值;将捕获子句的&改为=进行值捕获后,循环输出了正确结果。请问:Lambda的变量捕获发生在何时?是Lambda创建时还是线程执行时?若是后者,值捕获不应得到正确结果。
测试代码
#include <iostream> #include <string> #include <vector> #include <thread> int main() { std::thread myThread; { std::vector<int> testVar(10, 128); std::cout<<"Trying to create thread"<<std::endl; myThread = std::thread([&](){std::this_thread::sleep_for(std::chrono::seconds(3));for(int i=0; i<10; i++){std::cout<<testVar[i]<<std::endl;}}); } myThread.join(); }
引用捕获执行结果
Trying to create thread
1580344384
21851
1580269584
21851
128
128
128
128
128
128
值捕获执行结果
Trying to create thread
128
128
128
128
128
128
128
128
128
128
解答
Lambda的变量捕获发生在Lambda创建的时刻,而非线程执行时。
- 引用捕获逻辑:Lambda创建时,只是捕获了
testVar的内存地址。当代码块结束后,testVar作为局部变量被销毁,其占用的内存被系统回收。线程延迟3秒执行时,访问的是已经失效的内存区域,所以会输出随机的垃圾值(也就是你看到的乱码数字)。 - 值捕获逻辑:Lambda创建时,就把
testVar的完整内容拷贝到了Lambda对象内部。后续即使原testVar被销毁,线程执行时访问的是Lambda自身持有的那份独立拷贝,所以能稳定输出正确的128。
内容的提问来源于stack exchange,提问作者ddzzBowen
相关产品推荐
相关产品推荐

