c++ - std::对象 vector ,其中封装有 boost::thread

标签 c++ multithreading boost

如何创建对象的 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 上找到了类似的帖子。它提到了编译器支持的移动语义,但没有解释它是什么。 How can I add boost threads to a vector

谢谢。

最佳答案

这段代码有两个问题。

首先,线程在 boost::thread 后立即开始运行。对象已构造,因此您需要确保它访问的任何数据都已预先初始化 --- 即初始化 x在构造线程之前在成员初始化列表中。

其次,该线程使用this INSTRUMENT的指针对象,因此您的对象被绑定(bind)到特定的地址。 std::vector 复制周围的值:当您调用 push_back 时然后它将对象复制到 vector 中,如果必须分配新的内存块以腾出空间,则添加其他元素可能会复制其他元素。这就是您看到的析构函数调用的原因:构造了临时变量,push_back将其复制到 vector ,然后临时对象被破坏。

要解决此问题,您需要确保一旦构建了 INSTRUMENT对象无法移动或复制,因为拷贝具有错误的语义。通过将复制构造函数和赋值运算符设置为私有(private)且未实现(或者如果您有支持此新 C++11 构造的最新编译器,则将它们标记为已删除),或从 boost::noncopyable 派生来实现此目的。 。完成此操作后,您不再需要 shared_ptr对于线程来说,由于它不能共享,所以直接构造即可。

如果INSTRUMENT不可复制,您不能将其直接存储在 vector 中,因此请使用类似 boost::shared_ptr<INSTRUMENT> 的内容在 vector 中。这将允许 vector 自由复制和重新排列其元素,而不影响 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));
}

关于c++ - std::对象 vector ,其中封装有 boost::thread,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9407378/

相关文章:

c++ - 为什么 cout 不起作用?

c++ - 如何向前和向后扫描 __uint128_t(128 位)?

c++ - 如何在 C++ 中基于用户输入或没有模式的文件创建动态对象

c# - 关于锁性能/使用的 2 个问题

c# - 如何使用线程完成,然后重用线程?

c++ - 使用 boost::numeric_cast<double>(long) 是否有目的(即从 long 转换为 double)?

c++ - 使用 WASAPI 录制音频流

c++ - 使用 Boost.Spirit.Lex 和流迭代器

c++ - Boost状态图-使用状态图作为模板参数时出现编译错误

python - 我应该使用事件、信号量、锁、条件或其组合来管理安全退出我的多线程 Python 程序吗?