有人可以解释以下代码的行为吗?
当我将 lambda 显式转换为 std::function
时,lambda 正确捕获了我的变量 n
。
当它隐式转换为 std::function
(使用临时变量)时,捕获会失败。
我正在使用g++-4.9 (Ubuntu 4.9-20140406-1ubuntu1) 4.9.0 20140405(实验)[trunk revision 209157]
#include <chrono>
#include <iostream>
#include <memory>
#include <thread>
std::shared_ptr<std::thread> call(const std::function<void()>& functor)
{
// Execute our functor asynchronously
return std::make_shared<std::thread>([&functor]
{
// Make sure all temporary are deallocated
std::this_thread::sleep_for(std::chrono::seconds(1));
// Execute our functor
functor();
});
}
int main()
{
int n{};
std::cout << "in main " << &n << std::endl;
// -> in main 0x7fffd4e1a96c
auto lambda = [&n]
{
std::cout << "in lambda " << &n << std::endl;
};
// Here we do an explicit convertion to std::function
std::cout << "explicit convertion" << std::endl;
auto function = std::function<void()>{ lambda };
auto pThreadFunction = call(function);
pThreadFunction->join();
// -> in lambda 0x7fffd4e1a96c
// Here we use an implicit convertion to std::function
std::cout << "implicit convertion" << std::endl;
auto pThreadLambda = call(lambda);
pThreadLambda->join();
// -> in lambda 0
return 0;
}
最佳答案
为绑定(bind)到 const 引用函数参数而构造的临时变量的生命周期是包含该函数调用的完整表达式,因此您的线程函数引用的是悬空引用。
如果您可以保证变量的生命周期包含线程的生命周期,则应该仅通过引用将变量捕获到线程函数中,正如您在 function
是本地函数的情况下所做的那样main
中的变量。
一种替代方法是在构造临时的完整表达式中调用 join
:
call(lambda)->join();
另一个更通用的解决方案是通过线程函数中的值捕获仿函数
。
关于c++11 - 通过引用捕获时如何异步使用 C++11 lambda,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24283486/