为了在构造对象启动实际工作的背景线程时实现逻辑,我使用了这样的模式(简化):
class A {
std::thread t{&A::run, this};
std::atomic_bool done;
// variables are the question about
std::vector<std::thread> array_for_thread_management;
// ... and other members
protected:
void run() {
...
array_for_thread_management.push_back([](){...});
...
}
public:
A() = default;
// all other constructors deleted because of used
// some members like std::atomic_bool done;
~A() {
done = true;
bi::named_condition cnd{bi::open_only, "cnd"};
cnd.notify_one();
if (t.joinable())
t.join();
for(std::thread& worker : array_for_thread_management) {
if (worker.joinable()) worker.join();
}
}
};
如果我在主后台线程中添加子线程推送到 run() 成员中的向量中,则对象将挂在析构函数上。即使向量中没有真正的线程,只是在没有外部连接的情况下启动它,并尝试通过析构函数阻止它
当然,一旦在 run
方法中有了指针this
就可以通过此指针访问类成员。我想你的代码的问题在于线程是在初始化任何其他成员之前生成的,因为它是类定义中的第一个成员。我怀疑使用以下class A
定义,您在访问成员变量时不会有任何问题:
class A {
std::atomic_bool done;
// variables are the question about
int i;
std::string s;
std::vector<std::string> v;
// and only after everything above is initialized:
std::thread t{&A::run, this}; // spawn a thread
// ...
}
但是,就我个人而言,我更喜欢有一个单独的方法start()
该方法生成一个线程,而不是在类构造函数中隐式生成它。它可能看起来像这样:
class A
{
std::unique_ptr<std::thread> t;
std::atomic<bool> some_flag;
public:
void start()
{
t.reset(new std::thread(&A::run, this));
}
private:
void run()
{
some_flag.store(true);
}
};