如何创建std :: vector对象,每个对象都有一个boost :: thread封装在里面。
class INSTRUMENT {
public:
INSTRUMENT() : m_thread(new boost::thread(&INSTRUMENT::Start, this)) {
x = "abc";
}
~INSTRUMENT() {}
void Start();
public:
std::string x;
boost::shared_ptr<boost::thread> m_thread;
};
void INSTRUMENT::Start() {
try {
while (1) {
boost::this_thread::interruption_point();
std::cout << "here " << x << std::endl;
}
} catch (boost::thread_interrupted &thread_e) {
std::cout << "exit " << x << std::endl;
} catch (std::exception &e) {
}
}
std::vector<INSTRUMENT> m_inst_vector;
for (int i = 0; i < 5; i++) {
m_inst_vector.push_back(INSTRUMENT());
}
代码编译正常,但输出只是一些垃圾,而不是预期的“abc”。在调试中,我注意到每次调用.push_back()时都会调用~INSTRUMENT()。
由于当前设计的限制,我尝试不使用boost :: group_thread。只是想知道是否有可能有一个带有线程的对象的std :: vector,或者对类似设计的任何建议都会非常有帮助。
我在SO上找到了类似的帖子。它提到了编译器支持的move-semantics,但没有解释它是什么。 How can I add boost threads to a vector
感谢。
答案 0 :(得分:4)
此代码存在两个问题。
首先,线程在构造boost::thread
对象时立即开始运行,因此您需要确保它所访问的任何数据都是事先初始化的 - 即在成员初始化列表中初始化x
之前构建线程。
其次,线程使用this
对象的INSTRUMENT
指针,因此您的对象绑定到特定地址。 std::vector
复制值:当您调用push_back
时,它会将对象复制到向量中,如果必须有新的内存块,则添加其他元素可能会复制其他元素分配给腾出空间。这是你看到的析构函数调用的原因:临时构造,push_back
将它复制到向量,然后临时被破坏。
要解决此问题,您需要确保一旦构造,您的INSTRUMENT
对象就无法移动或复制,因为副本具有错误的语义。通过使您的复制构造函数和赋值运算符为私有和未实现(或者如果您有一个支持此新C ++ 11构造的最新编译器将其标记为已删除)或从boost::noncopyable
派生来执行此操作。完成此操作后,您不再需要线程shared_ptr
,因为它无法共享,因此您可以直接构建它。
如果INSTRUMENT
不可复制,则无法将其直接存储在矢量中,因此请在矢量中使用boost::shared_ptr<INSTRUMENT>
之类的内容。这将允许向量自由地复制和重新组织其元素,而不会影响INSTRUMENT
对象的地址,并确保它在最后被正确销毁。
class INSTRUMENT: boost::noncopyable {
public:
INSTRUMENT() : x("abc"),m_thread(&INSTRUMENT::Start, this) {
}
~INSTRUMENT() {}
void Start();
public:
std::string x;
boost::thread m_thread;
};
void INSTRUMENT::Start() {
try {
while (1) {
boost::this_thread::interruption_point();
std::cout << "here " << x << std::endl;
}
} catch (boost::thread_interrupted &thread_e) {
std::cout << "exit " << x << std::endl;
} catch (std::exception &e) {
}
}
std::vector<boost::shared_ptr<INSTRUMENT> > m_inst_vector;
for (int i = 0; i < 5; i++) {
m_inst_vector.push_back(boost::shared_ptr<INSTRUMENT>(new INSTRUMENT));
}
答案 1 :(得分:1)
编辑:您的代码中存在竞争条件。线程在x
初始化之前启动。
您应该将矢量更改为vector<boost::shared_ptr<INSTRUMENT> >
,然后从boost::shared_ptr
内删除INSTRUMENT
。
class INSTRUMENT {
public:
INSTRUMENT() {
x = "abc";
m_thread = boost::thread(&INSTRUMENT::Start, this)
}
~INSTRUMENT() {}
void Start();
public:
std::string x;
boost::thread m_thread;
};
for (int i = 0; i < 5; i++) {
m_inst_vector.push_back(boost::shared_ptr<INSTRUMENT>(new INSTRUMENT()));
}