2

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

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

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

这是潜在的危险,因为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这样一个微不足道的问题,课程似乎有很多开销。

4

1 回答 1

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; }
};
于 2013-04-01T22:16:21.630 回答