[英]std::vector of objects with a boost::thread encapsulated insde
如何创建对象的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上找到类似的线程。 它提到了编译器支持的移动语义,但没有解释它是什么。 如何向矢量添加增强线程
谢谢。
此代码有两个问题。
首先,线程将立即开始运行boost::thread
对象的构造,因此您需要确保对其访问的所有数据进行预先初始化---即在构造线程之前在成员初始化列表中初始化x
。
其次,线程使用INSTRUMENT
对象的this
指针,因此您的对象绑定到特定地址。 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));
}
编辑 :您的代码中有一个竞争条件。 线程在x
初始化之前开始。
您应该将向量更改为vector<boost::shared_ptr<INSTRUMENT> >
,然后从INSTRUMENT
内部删除boost::shared_ptr
。
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()));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.