在对象构造函数中初始化boost线程?

时间:2013-04-01 20:48:59

标签: c++ constructor boost-thread

我想为boost线程编写一个包装器来专门化一个线程模型。我的run()函数将成为使用boost::thread作为聚合线程对象的同一个类的成员函数。考虑:

class Thread {
public:
  Thread(...) : m_thread(&Thread::run, this) {}

private:
  void run() { ... }
  boost::thread m_thread;
};

This is potentially dangerous因为this尚未完全构建。但是,如果我可以保证run()使用的对象的所有成员在初始化boost线程之前被初始化,那么这实际上是否可以被认为是安全的?

我能想到的唯一解决方法是保证安全性是有一个子类来保证Thread的构造函数可以使用的对象的完整构造:

class Thread {
public:
  Thread(...) : m_impl(...), m_thread(&ThreadImpl::run, &m_impl) {}

private:
  class ThreadImpl {
    ThreadImpl(...) { }
    void run() { ... }
  }

  ThreadImpl m_impl;
  boost::thread m_thread;
};

有没有一种常见的方法可以做到这一点?对于这样一个微不足道的问题,ThreadImpl类似乎有很多开销。

1 个答案:

答案 0 :(得分:2)

声明成员的顺序(不是初始化列表中的顺序,所以要小心)是构造的顺序。只要构造了所有成员足以建立一致状态,如果你声明线程成员是最后的,那么你应该没问题。

但是,如果您不想依赖它,可以在构造函数的末尾以类似这样的方式启动您的线程:

// Constructor
MyThread() {
  // Initialize everything else...

  boost::thread t(boost::bind(&MyThread::run, this));
  m_thread.swap(t);
}

关于使用this指针的安全性,标准在12.6.2中说:

  

注意:因为 mem-initializer 是在范围内评估的   构造函数, this 指针可以在表达式列表中使用    mem-initializer 用于引用正在初始化的对象。

  

成员函数(包括虚拟成员函数,10.3)可以   要求正在建造的物体。

您只需要避免访问尚未构建的内容。这可以包括在初始化所有基类之前调用​​成员函数:

class Derived : public Base {
public:
  Derived()
    : Base(foo())  // foo() undefined because base class not initialized
  {
  }

  int foo() { return 0; }
};