c++ 将超出作用域的lambda函数传递给std::thread是否安全

kd3sttzy  于 2023-01-28  发布在  其他
关注(0)|答案(1)|浏览(130)

考虑以下代码:

#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;
}
vltsax25

vltsax251#

作为评论的摘要:
lambda是复制的(如果声明在原处,则是移动的),因此不会出现问题。
你必须担心的捕获:不要通过引用捕获可能超出作用域的对象,或者如果您传递的对象可能在线程执行期间被删除(即使复制,也要考虑到指向对象的原始指针)。
作为一个扩展,如果使用std::bind传递一个方法,并且对象超出范围或被删除,则同样适用。

相关问题