![](/img/trans.png)
[英]Is it safe to pass arguments by reference into a std::thread function?
[英]Is it safe to pass const reference to temporary/annonymous lambda into std::thread constructor?
继这个问题之后: 可以通过参考传递一段时间吗?
我有一个固定的代码片段:
// 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()将返回并且temp-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 &&
,我认为这对于临时变量是好的。
那么我在我的代码片段中做了什么危险(即ref超出范围)或更正(即temp被移动,一切都很好)? 还是两个?
另一种方法是传递我的价值(制作副本),在这种情况下无论如何都不是那么糟糕。
临时的确移动,但它是“内部”一个,给个说法std::thread
。
该临时文件包含对“外部”临时文件的引用, start_work
的参数,以及在start_work
返回后其生命周期结束的start_work
。
因此,您的“内部”lambda对象包含对在执行期间可能存在或可能不存在的对象的引用,这是非常不安全的。
lambda是C ++中的匿名struct
。 如果我们要将片段翻译成没有lambdas的等效片段,它就会变成
template <typename Functor>
void start_work(const Functor &worker_fn)
{
struct lambda {
const Functor& worker_fn;
auto operator()() const { worker_fn(); }
};
worker_thread = std::thread(lambda{worker_fn});
}
lambda
有一个非基于堆栈的const引用作为成员,一旦start_work
返回就会start_work
,无论lambda
对象本身是否被复制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.