考虑以下代码:
#include <iostream>
#include <thread>
#include <chrono>
int main()
{
std::thread t;
{
auto my_lambda = []{
int idx = 0;
while (true) {
std::this_thread::sleep_for (std::chrono::seconds(1));
std::cout << idx ++ << std::endl;
}
};
t = std::thread(my_lambda);
}
t.join();
return 0;
}
线程运行超出作用域的lambda函数是否安全?
我看到std::thread
的构造函数为输入函数Function&& f
获取了一个通用引用,并且lambda被转换为struct,因此如果struct的示例在作用域中被示例化,线程将运行悬空引用的operator()
。
{
struct lambda_translated { void operator()(){ ... } };
lambda_translated instance;
t = std::thread(instance);
}
不过,我不确定我的推理是否正确。
附带问题:如果我在std::thread
构造函数中将lambda声明为R值,行为是否会改变:
#include <iostream>
#include <thread>
#include <chrono>
int main()
{
std::thread t;
{
t = std::thread([]{
int idx = 0;
while (true) {
std::this_thread::sleep_for (std::chrono::seconds(1));
std::cout << idx ++ << std::endl;
}
});
}
t.join();
return 0;
}
1条答案
按热度按时间vltsax251#
作为评论的摘要:
lambda是复制的(如果声明在原处,则是移动的),因此不会出现问题。
你必须担心的捕获:不要通过引用捕获可能超出作用域的对象,或者如果您传递的对象可能在线程执行期间被删除(即使复制,也要考虑到指向对象的原始指针)。
作为一个扩展,如果使用
std::bind
传递一个方法,并且对象超出范围或被删除,则同样适用。