接着这个问题: can-a-temperary-lambda-by-passed-by-reference?
我有一个固定的代码片段:
// global variable
std::thread worker_thread;
// Template function
template <typename Functor>
void start_work(const Functor &worker_fn) // lambda passed by const ref
{
worker_thread = std::thread([&](){
worker_fn();
});
}
这被称为“这样做”:
void do_work(int value)
{
printf("Hello from worker\r\n");
}
int main()
{
// This lambda is a temporary variable...
start_work([](int value){ do_work(value) });
}
这似乎可以工作,但我担心传递一个临时 lambda 到线程构造函数中,因为线程将运行,但函数 start_work() 将返回且临时 lambda 将超出其作用域。
然而,我查看了定义如下的 std::thread 构造函数:
thread() noexcept; (1) (自 C++11 起)
thread( thread&& other ) noexcept; (2) (自 C++11 起)
template< class Function, class... Args > explicit thread( Function&& f, Args&&... args ); (3) (自 C++11 起)
thread(const thread&) = delete; (4) (自 C++11 起)
所以我认为会调用构造函数 3:
template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args );
我很困难地理解这里写的内容,但看起来好像是试图移动lambda&&
,我认为对于临时变量来说这是可以的。
那么我在我的代码片段中所做的是危险的(即参考超出作用域),还是正确的(即临时移动,一切顺利)?或者两者都不是?
另一个选择就是传递我的值(复制一份),在这种情况下也不算太糟糕。
const &
传递给std::thread
中的临时对象,是可以的。但这不是你正在做的事情。问题在于你正在通过引用捕获一个临时对象到 lambda 表达式中,这不是同一件事情,也不适用于这种情况。 - François Andrieuxstart_work(do_work);
和worker_thread = std::thread(worker_fn);
执行相同的操作(两者都缺少do_work
调用的value
参数)。 - Caleth