Reputation: 941
I would like to hold a thread in a member variable of some class. The following code snippet shows what I would like to achieve:
#include <iostream>
#include <thread>
#include <vector>
class Test {
public:
std::thread& t;
Test(std::thread&& rt) : t(rt) {}
};
int main()
{
std::vector<Test> tests;
{
std::thread t ([]{
std::cout << 1;
});
tests.push_back(Test(std::move(t)));
}
for(Test mytest : tests)
{
mytest.t.join();
}
}
The code will break at the join() line. The error is:
terminate called without an active exception
Aborted (core dumped)
Why can't I call the thread via mytest.t when the scope of the original thread creation was left?
Upvotes: 1
Views: 856
Reputation: 33944
In your class you have a reference to a thread, not a thread object:
std::thread& t;
^
Which means the following sequence will happen:
{
std::thread t ([]{
std::cout << 1;
}); // 1. Thread is created.
tests.push_back(Test(std::move(t))); // 2. Reference to moved thread is taken
// and after move thread is destroyed.
// 3. Now the thread is destroyed,
// but not joined which will call `std::terminate`
// (Thanks @tkausl)
}
If you make your class std::thread t
the move will work.
Upvotes: 3
Reputation: 1894
As mentioned by @tkausl that it is a reference, the {}
destroys the thread object once it is out of scope and your reference is no longer valid. Further you need to modify your loop so that it does not create a copy of the original Test
object. After modifications this becomes:
class Test {
public:
std::thread& t;
Test(std::thread&& rt) : t(rt) {}
};
int main()
{
std::vector<Test> tests;
std::thread t ([]{
std::cout << 1;
});
tests.push_back(Test(std::move(t)));
for(Test& mytest : tests)
{
mytest.t.join();
}
}
Upvotes: 0
Reputation: 5166
Since std::thread are movable but not copyable, you can do like so:
class Test {
public:
std::thread t;
Test(std::thread&& rt) : t(std::move(rt)) {}
};
int main()
{
std::vector<Test> tests;
{
std::thread t([] {
std::cout << 1;
});
tests.push_back(Test(std::move(t)));
}
for (Test& mytest : tests)
{
mytest.t.join();
}
}
Upvotes: 6