Passing object by reference to std::thread in C++11
Explicitly initialize the thread with a reference_wrapper
by using 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
:
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
).
Based on this comment, this answer elaborates on the reason why the arguments are not passed by reference to the thread function by default.
Consider the following function SimpleThread()
:
void SimpleThread(int& i) {
std::this_thread::sleep_for(std::chrono::seconds{1});
i = 0;
}
Now, imagine what would happen if the following code compiled (it does not compile):
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 passed by 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.
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.