簡體   English   中英

具有boost :: thread封裝的insde的對象的std :: vector

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM