为什么std::thread采用函数由右值运行

Why does std::thread take function to run by rvalue?

本文关键字:函数 运行 std thread 为什么      更新时间:2023-10-16

关于std::thread有一件事我不明白:为什么std::thread的构造函数使用函数由右值运行?

我通常想运行一个具有一些成员的Functor到另一个线程。像这样:

struct Function
{
    void operator() ( /* some args */)
    {
        /* some code */
    }
    /* some members */
}

void run_thread()
{
    Functor f( /* some data */);
    std::thread thread(f, /* some data */);
    /* do something and wait for thread to finish */
}

对于std::thread的当前实现,我必须确保我的对象正在实现移动语义。我不明白为什么我不能通过参考。

额外的问题是:用右值来指函数意味着什么?Lambda表达式?

在您的run_thread方法中,f是一个自动变量。这意味着在作用域的底部f将被销毁。你声称你将"等待线程完成",但编译器/运行时系统并不知道!它必须假设f将被删除,可能在应该调用其方法的线程有机会启动之前。

通过复制(或移动)f,运行时系统可以控制其f副本的寿命,并可以避免一些非常棘手、难以调试的问题。

std::reference_wrapper将向包装的对象公开一个operator()。如果您愿意进行手动终身维护,std::thread t(std::ref(f));将参考运行f

当然,在您的代码中,这会导致未定义的行为,因为您没有正确管理生命周期。


最后,请注意,原始thread是一个糟糕的"客户端代码"工具。async稍微好一点,但实际上您想要一个包含packaged_tasks和futures以及条件变量的任务队列。C++11添加了足够的线程支持来编写一个像样的线程系统,但它提供了原语,而不是好的"客户端代码"工具。

在玩具程序中,这可能就足够了。