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

时间:2018-04-13 08:18:28

标签: c++ multithreading c++11

我正在尝试使用bar重新构建在thread类析构函数中销毁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 << "Exiting\n";
}

1 个答案:

答案 0 :(得分:0)

这看起来像是处理线程和智能指针的坏方法,虽然我不是一些C ++ Guru,但我认为这是一种用C ++编写整体代码的坏方法(几乎肯定会出现可读性可维护性等问题。 )。

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

~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));
}