在 C++11 中通过引用 std::thread 传递对象
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34078208/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Passing object by reference to std::thread in C++11
提问by austinmarton
Why can't you pass an object by reference when creating a std::thread
?
为什么在创建对象时不能通过引用传递对象std::thread
?
For example the following snippit gives a compile error:
例如,以下代码段给出了编译错误:
#include <iostream>
#include <thread>
using namespace std;
static void SimpleThread(int& a) // compile error
//static void SimpleThread(int a) // OK
{
cout << __PRETTY_FUNCTION__ << ":" << a << endl;
}
int main()
{
int a = 6;
auto thread1 = std::thread(SimpleThread, a);
thread1.join();
return 0;
}
Error:
错误:
In file included from /usr/include/c++/4.8/thread:39:0,
from ./std_thread_refs.cpp:5:
/usr/include/c++/4.8/functional: In instantiation of ‘struct std::_Bind_simple<void (*(int))(int&)>':
/usr/include/c++/4.8/thread:137:47: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(int&); _Args = {int&}]'
./std_thread_refs.cpp:19:47: required from here
/usr/include/c++/4.8/functional:1697:61: error: no type named ‘type' in ‘class std::result_of<void (*(int))(int&)>'
typedef typename result_of<_Callable(_Args...)>::type result_type;
^
/usr/include/c++/4.8/functional:1727:9: error: no type named ‘type' in ‘class std::result_of<void (*(int))(int&)>'
_M_invoke(_Index_tuple<_Indices...>)
^
I've changed to passing a pointer, but is there a better work around?
我已改为传递指针,但有更好的解决方法吗?
回答by ShadowRanger
Explicitly initialize the thread with a reference_wrapper
by using std::ref
:
明确初始化一个线程reference_wrapper
使用std::ref
:
auto thread1 = std::thread(SimpleThread, std::ref(a));
(or std::cref
instead of std::ref
, as appropriate). Per notes from cppreference on std:thread
:
(或std::cref
代替std::ref
,视情况而定)。根据cppreference 上的std:thread
注释:
The arguments to the thread function are moved or copied by value. If a reference argument needs to be passed to the thread function, it has to be wrapped (e.g. with
std::ref
orstd::cref
).
线程函数的参数按值移动或复制。如果需要将引用参数传递给线程函数,则必须对其进行包装(例如使用
std::ref
或std::cref
)。
回答by u8012646
Based on this comment, this answer elaborates on the reason why the arguments are not passed by referenceto the thread function by default.
基于此评论,此答案详细说明了默认情况下不通过引用传递给线程函数的参数的原因。
Consider the following function SimpleThread()
:
考虑以下函数SimpleThread()
:
void SimpleThread(int& i) {
std::this_thread::sleep_for(std::chrono::seconds{1});
i = 0;
}
Now, imagine what would happenif the following code compiled (it does notcompile):
现在,想象一下会发生,如果下面的代码编译(它并没有编译):
int main()
{
{
int a;
std::thread th(SimpleThread, a);
th.detach();
}
// "a" is out of scope
// at this point the thread may be still running
// ...
}
The argument a
would be passedby reference to SimpleThread()
. The thread may still be sleeping in the function SimpleThread()
after the variable a
has already gone out of scope and its lifetime has ended. If so, i
in SimpleThread()
would actually be a dangling reference, and the assignment i = 0
would result in undefined behaviour.
参数a
将通过引用传递给SimpleThread()
。SimpleThread()
在变量a
已经超出范围并且其生命周期结束后,线程可能仍在函数中休眠。如果是这样,i
inSimpleThread()
实际上将是一个悬空引用,并且赋值i = 0
将导致未定义的行为。
By wrapping reference arguments with the class template std::reference_wrapper
(using the function templates std::ref
and std::cref
) you explicitly express your intentions.
通过使用类模板std::reference_wrapper
(使用函数模板std::ref
和std::cref
)包装引用参数,您可以明确表达您的意图。