Similar questions have been asked before, however none seem to be explaining some behavior I observed. Some answers have already explained why you need to have the vector of pointers to threads (copy vs move). A few follow up questions:
I'm trying to instantiate the pointers in a temp variable and push the temp variable to the vector. It fails, but works when using
std::moveor when putting the whole instantiation in thepush_back(). Why isstd::movenecessary sincepush_back()has the const reference as the argument, i.e. what's the difference?Why does accessing threads by subscription
greeters[i]throw a segmentation fault? The program runs for a few iterations and then crashes?Similar to above but with iterators. Only using
back()seems to work fine. Does it have anything to do with the const reference return type? If so what?
Compile using g++ -std=c++20 -pthread -o thread thread.cpp.
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
std::mutex m;
int cnt = 0;
void say_hello(int id)
{
m.lock();
cnt++;
std::cout << cnt << " Hello from " << id << std::endl;
m.unlock();
}
int main()
{
int n = 20;
std::vector<std::unique_ptr<std::thread>> greeters(n);
for (int i = 0; i < n; i++) {
// auto tmp = std::unique_ptr<std::thread>(new std::thread( [&i]() { return say_hello(i); } ) );
// greeters.push_back(tmp); // error: no matching function for call to 'construct_at'
// greeters.push_back(std::move(tmp)); // works fine
greeters.push_back(std::unique_ptr<std::thread>(new std::thread( [&i]() { return say_hello(i); } ) )); // works fine
}
for (int i = 0; i < n; i++ ) {
auto val = std::move(greeters[i]); // throws segmentation fault
// auto val = std::move(greeters.back()); // works fine
// greeters.pop_back();
val -> join();
}
// std::vector<std::unique_ptr<std::thread>>::iterator ptr;
// for (ptr = greeters.begin(); ptr < greeters.end(); ptr++) {
// (*ptr) -> join(); // throws segmentation fault
// }
return 0;
}