I am learning C++ std thread with lambda function. In the following example, I don't know why the third argument (the lambda) for for_each
has to use std::thread &t
as its parameter.
#include <iostream>
#include <thread>
#include <vector>
#include <algorithm>
int main()
{
// vector container stores threads
std::vector<std::thread> workers;
for (int i = 0; i < 5; i++) {
workers.push_back(std::thread([]()
{
std::cout << "thread function\n";
}));
}
std::cout << "main thread\n";
std::for_each(workers.begin(), workers.end(), [](std::thread &t)
{
t.join();
});
return 0;
}
With std::thread t
, it gives the following compilation error:
In file included from /usr/include/c++/4.8.2/algorithm:62:0,
from foo.cc:6:
/usr/include/c++/4.8.2/bits/stl_algo.h: In instantiation of ‘_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = __gnu_cxx::__normal_iterator<std::thread*, std::vector<std::thread> >; _Funct = main()::__lambda1]’:
foo.cc:20:3: required from here
/usr/include/c++/4.8.2/bits/stl_algo.h:4417:14: error: use of deleted function ‘std::thread::thread(std::thread&)’
__f(*__first);
^
In file included from foo.cc:2:0:
/usr/include/c++/4.8.2/thread:125:5: error: declared here
thread(thread&) = delete;
^
foo.cc:18:64: error: initializing argument 1 of ‘main()::__lambda1’
std::for_each(workers.begin(), workers.end(), [](std::thread t) {
I also checked that if I replace std::thread
with int
in my example, using int t
as the third argument for for_each
also works.
std::for_each(workers.begin(), workers.end(), [](std::thread &t)
{
t.join();
});
can be translated to
for (auto it = workers.begin(), end = workers.end(); it != end; ++it)
{
std::thread &t = *it; // take a reference to the element, this is fine
t.join();
}
When you leave out the &
and take the thread by value then you get
for (auto it = workers.begin(), end = workers.end(); it != end; ++it)
{
std::thread t = *it; // make a copy of the element, boom
t.join();
}
You make a copy, but std::thread
can't be copied, so you get an error. For the manual loop you could "fix" that by using std::move
like
for (auto it = workers.begin(), end = workers.end(); it != end; ++it)
{
std::thread t = std::move(*it); // now we move into t
t.join();
}
and you can get this same behavior in std::for_each
by using std::make_move_iterator
like
std::for_each(std::make_move_iterator(workers.begin()),
std::make_move_iterator(workers.end()),
[](std::thread t)
{
t.join();
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.