移动包含正在运行的std :: thread成员的对象

fan*_*hin 7 c++

如何正确使用移动语义与对象中的运行线程?

样品:

#include <iostream>
#include <thread>
#include <vector>

struct A {
    std::string v_;
    std::thread t_;

    void start() {
        t_ = std::thread(&A::threadProc, this);
    }

    void threadProc() {
        for(;;) {
            std::cout << "foo-" << v_ << '\n';
            std::this_thread::sleep_for(std::chrono::seconds(5));
        }
    }
};

int main() {
    A m;
    {
        A a;
        a.v_ = "bar";
        a.start();
        m = std::move(a);
    }
    std::cout << "v_ = " << m.v_ << '\n'; /* stdout is 'v_ = bar' as expected    */
                                          /* but v_ in thread proc was destroyed */
                                          /* stdout in thread proc is 'foo-'     */
    m.t_.join();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我希望在移动后使用类成员,但是当我移出范围时,类成员被销毁并且std :: thread被移动到新对象中,但是它开始使用被销毁的成员.

在我看来,因为this在线程初始化中使用指针.

在这种情况下,最佳做法是什么?

MSa*_*ers 5

正如所写,它不会起作用。移动后,线程m.t_指的是仍在运行的线程a.threadProc()。这将尝试打印a.v_.

片段甚至有两个问题:不仅被a.v_移出(因此它的值未指定),而且它也即将在另一个线程中被销毁,并且该销毁在使用后没有排序。

由于对象需要存活足够长的时间,并且由于线程而具有非平凡的生命周期,因此您需要将其从堆栈中取出并从向量中取出。相反,用于std::shared_ptr管理生命周期。您可能需要将它传递shared_ptr给线程,以避免在线程开始运行之前对象可能过期的竞争条件。你不能依赖std:shared_from_this.