如何避免派生类提前销毁?

Rob*_*Lew 3 c++ multithreading

我在基于线程中启动了一个线程。该线程中调用了一个纯虚函数。我在派生类中实现它。

#include <iostream>
#include <memory>
#include <thread>
struct Base {
  std::unique_ptr<std::thread> th;
  virtual void foo() = 0;
  void bar() { 
    th = std::make_unique<std::thread>(
      [this](){
        foo();
      }
    );
  }
  virtual ~Base(){
    th->join();
  }
};

struct Derived : public Base {
  virtual void foo() override {
    std::cout << "impl in derived" << std::endl;
  }
};
int main() {
  Derived d;
  d.bar();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,在这些代码中,派生对象将在基础对象之前解构。

pure virtual method called
terminate called without an active exception
Aborted (core dumped)
Run Code Online (Sandbox Code Playgroud)

这种情况下如何控制销毁顺序呢?

utn*_*tim 5

这是一个并发问题,发生的是未定义的行为。如果您构建不同的配置(例如,从调试切换到发布构建),应用程序完全有可能会出现不同的情况。

具体来说,我相信当 main 完成执行并超出范围时,您的线程才刚刚启动。这会调用所有析构,最终(在您的实现中) foo 指向基类实现(在派生析构函数的末尾),然后 main 在基析构函数中被阻止 - 在 join 调用中。

怎么修:

将连接移动到单独的函数中并显式调用它:

struct Base {
  std::unique_ptr<std::thread> th;
  virtual void foo() = 0;
  void bar() { 
    th = std::make_unique<std::thread>(
      [this](){
        foo();
      }
    );
  }
  virtual ~Base() = default;

  void join() { th->join(); }
};

int main() {
  Derived d;
  d.bar();
  d.join(); // prevent the destruction of the derived part
            // and main blocking before completing the base
            // destructor execution.
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • [简体](https://godbolt.org/z/nvEvhdGP5) (3认同)