有人可以解释以下代码的行为吗?
当我明确地将我的lambda转换为std::function
时,lambda正确地捕获了我的变量n
。
当隐式转换为std::function
(使用临时)时,捕获失败。
我正在使用g++-4.9 (Ubuntu 4.9-20140406-1ubuntu1) 4.9.0 20140405 (experimental) [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;
}
答案 0 :(得分:2)
用于绑定到const
引用函数参数的临时构造的生命周期是包含该函数调用的完整表达式,因此您的线程函数引用了悬空引用。
如果可以保证变量的生命周期包含线程的生命周期,那么只应通过引用将变量捕获到线程函数中,就像function
是main
中的局部变量一样。 {1}}。
一种替代方法是在构造临时的全表达式中调用join
:
call(lambda)->join();
另一个更通用的解决方案是在线程函数中按值捕获functor
。