[英]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.