简体   繁体   English

为什么std :: thread需要函数来运行rvalue?

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

There is one thing about std::thread which I don't understand: why the constructor of std::thread takes function to run by rvalue? 关于std::thread一点我不明白:为什么std::thread的构造函数需要函数来运行rvalue?

I usually want to run a Functor with some members to another thread. 我通常想要将一些成员的Functor运行到另一个线程。 Like this: 像这样:

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 */
}

With current implementation of std::thread I must be sure my object is implementing move semantics. 使用std::thread当前实现,我必须确保我的对象正在实现移动语义。 I don't get why cannot I pass it by reference. 我不明白为什么我不能通过引用传递它。

Extra question is: what does it mean to refer to function by rvalue? 额外的问题是:通过rvalue引用函数意味着什么? Lambda expression? Lambda表达?

In your run_thread method f is an auto variable. 在run_thread方法中, f是一个自动变量。 That means at the bottom of the scope f will be destroyed. 这意味着在范围的底部f将被销毁。 You claim that you will "wait for the thread to finish" but the compiler/runtime system does not know that! 你声称你将“等待线程完成”,但编译器/运行时系统不知道这一点! It has to assume that f will be deleted, possibly before the thread that is supposed to call its method has a chance to start. 它必须假设f将被删除,可能在应该调用其方法的线程有机会启动之前。

By copying (or moving) the f , the run time system gains control of the lifetime of its copy of f and can avoid some really nasty, hard to debug problems. 通过复制(或移动) f ,运行时系统可以控制其f副本的生命周期,并且可以避免一些非常讨厌,难以调试的问题。

std::reference_wrapper will expose an operator() to the wrapped object. std::reference_wrapper会将operator()暴露给包装对象。 If you are willing to do the manual lifetime maintenance, std::thread t(std::ref(f)); 如果你愿意做手动终身维护, std::thread t(std::ref(f)); will run f by reference. 将通过引用运行f

Of course in your code, this induces undefined behaviour as you did not manage lifetimes properly. 当然,在您的代码中,这会导致未定义的行为,因为您没有正确管理生命周期。


Finally, note that raw thread is a poor "client code" tool. 最后,请注意原始thread是一个糟糕的“客户端代码”工具。 async is a touch better, but really you want a task queue with packaged_task s and future s and condition variables. async是一种更好的触摸,但实际上你需要一个带有packaged_taskfuture s和条件变量的任务队列。 C++11 added enough threading support to write a decent threading system, but it provides primitives, not good "client code" tools. C ++ 11增加了足够的线程支持来编写一个不错的线程系统,但它提供了原语,而不是好的“客户端代码”工具。

In a toy program it may be enough. 在玩具程序中,它可能就足够了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么std :: shuffle采用右值引用? - Why does std::shuffle take an rvalue reference? 为什么std :: move将rvalue引用作为参数? - Why does std::move take rvalue reference as argument? std 线程构造函数是否采用可变参数线程 function? - Does std thread constructor take variadic thread function? 为什么std :: forward将lvalue和rvalue转换为右值引用? - Why does std::forward converts lvalue and rvalue to rvalue reference? 为什么std :: tuple会分解为rvalue引用 - Why does std::tuple decompose into rvalue references std :: thread和rvalue参考 - std::thread and rvalue reference 为什么这个简单的lambda在std :: thread中始终比在gcc 4.9.2的main函数中运行更快? - Why does this simple lambda consistently run faster inside an std::thread than inside the main function with gcc 4.9.2? 为什么 std::thread 在要求运行重载的 function 时会抛出错误? - why does std::thread throws an error when it's asked to run an overloaded function? 为什么右值 object 没有通过右值参数移动到 function? - Why does rvalue object does not get moved to function with rvalue parameter? 为什么 std::move 复制右值或 const 左值函数参数的内容? - Why does std::move copy contents for a rvalue or const lvalue function argument?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM