使用线程销毁类析构函数中的shared_ptr成员变量

Destroying a shared_ptr member variable in the class destructor using a thread

本文关键字:shared ptr 变量 成员 析构函数 线程      更新时间:2023-10-16

我正在尝试使用thread重新创建销毁bar类析构函数中的shared_ptr成员变量,我认为这可能是堆损坏的原因。我个人觉得在析构函数中使用线程很奇怪,所以我希望 SO 的意见。

指针可能比应用程序寿命更长,所以使用detach更可取。如果使用detach则不调用析构函数,但如果join,则它可以工作。

1(以这种方式重置智能指针是错误的吗?

2( 为什么在使用std::thread::detach()时不调用析构函数?

#include <iostream>
#include <thread>
#include <memory>
#include <chrono>
using namespace std;
class foo
{
    public:
    foo(){longcomputation();}
    void longcomputation() 
    { 
        std::cout<<" long computation called n";
        std::this_thread::sleep_for(std::chrono::seconds(1)); 
    }
};
class bar
{
    public:
    bar(): foo_(std::make_shared<foo>()) {}
    ~bar() 
    {
        std::thread([foo = std::move(foo_)] () mutable
        {
          foo.reset();
          std::cout<<" bar dctor called n";
        }).detach();  // ==========> works with join however
    }
    private:
    std::shared_ptr<foo> foo_;
};

int main()
{
    bar bar1;
    std::this_thread::sleep_for(std::chrono::seconds(3));
    std::cout << "Exitingn";
}

看起来确实是处理线程和智能指针的糟糕方法,虽然我不是C++大师,但我会说这是一种糟糕的编码方式C++整体(几乎肯定会存在可读性可维护性等问题(。

来到析构

函数,在调度分离的线程之前,析构函数退出,销毁foo_对象,因此std::move(foo_)失败。当你使用 join() 而不是 detach() ,你正在使析构函数等待线程,这就是它工作的原因。如果我们在分离线程后在析构函数中构建睡眠,它也会起作用:

~bar()
{
    std::thread([foo = std::move(foo_)] () mutable
    {
      foo.reset();
      std::cout<<" bar dctor called n";
    }).detach();  // ==========> works with join however
    // this works too
    std::this_thread::sleep_for(std::chrono::seconds(1));
}