线程作为类的成员变量

Thread as member variable of class

本文关键字:成员 变量 线程      更新时间:2023-10-16

我想在某个类的成员变量中保存一个线程。以下代码片段显示了我想要实现的目标:

#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();
}
}

代码将在 join() 行处中断。错误是:

terminate called without an active exception
Aborted (core dumped)

为什么当原始线程创建的范围离开时,我不能通过 mytest.t 调用线程?

由于 std::thread 是可移动的,但不可复制,你可以这样做:

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();
}
}

在你的类中,你有一个对线程的引用,而不是一个线程对象:

std::thread& t;
^

这意味着将发生以下顺序:

{
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)
}   

如果你让你的班级std::thread t移动将起作用。

正如 @tkausl 提到的,它是一个引用,一旦线程对象超出范围并且您的引用不再有效,{}就会销毁该对象。此外,您需要修改循环,使其不会创建原始Test对象的副本。修改后,这将变为:

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();
}
}