shared_ptr.reset() not deleting

shared_ptr.reset() not deleting

本文关键字:not deleting reset ptr shared      更新时间:2023-10-16

我开始学习shared_ptr和weak_ptr。理论上一切看起来都很简单。但当我开始测试时,嗯。。。我有一个非常简单的程序:

#include <iostream>
#include <memory>
using namespace std;
class Second
{
public:
    Second()
    {
        cout << "Second created" << endl;
    }
    ~Second()
    {
        cout << "Second deleted" << endl;
    }
};
class Main
{
public:
    shared_ptr<Second> second;
    Main()
    {
        cout << "Main created" << endl;
        second = make_shared<Second>(*(new Second()));
    }
    ~Main()
    {
        second.reset();
        cout << "Main deleted" << endl;
    }
};
void fun()
{
    shared_ptr<Main> main = make_shared<Main>(*(new Main()));
}
int main()
{
    cout << "Program started" << endl;
    fun();
    cout << "Program ended" << endl;
    return 0;
}

问题是,第二条永远不会被删除。这是我的输出:

Program started
Main created
Second created
Main deleted
Program ended

发生了什么事?我想,如果我重置shared_ptr,以及它存在的最后一个shared_ptr,对象就会自动删除。

您初始化共享指针时出错。使用make_shared时根本不需要使用new。传递给make_shared的参数将转发给正在生成的类的构造函数。

因此,在您的代码中,make_shared调用应该如下所示:

shared_ptr<Main> main = make_shared<Main>();

shared_ptr<Second> main = make_shared<Second>();

相反,您所做的是泄露每个类的一个版本(通过显式使用new而不是删除它),然后将泄露的值复制到第二个版本中。通过将表达式拆分为多行,我们可以更容易地看到你做错了什么:

Second *p = new Second;
shared_ptr<Second> ss = make_shared<Second>(*p); // Calls the Second class copy constructor
// p is never deleted, so it is leaked.

正如我所说,情况非常复杂,所以我需要一个模式。

class Main {
public:
    shared_ptr<Second> second;
    Main()
    {
        cout << "Main created" << endl;
        second = make_shared<Second>(*(new Second()));
    }
    ~Main()
    {
        second.reset();
        cout << "Main deleted" << endl;
    }
};
void fun()
{
    shared_ptr<Main> main = make_shared<Main>(*(new Main()));
}

在创建main之后,我们有:

 <anon: Second> (leaked)
 <anon: Main>   (leaked)
             
             |---> <Main.second: Second>
             /
 <main: Main>

注意,main.second是从<anon>.second复制的,因此,由于它们是shared_ptr<Second>,所以它们都指向Second的同一实例。

然后,main死亡,我们只剩下:

<anon: Second> (leaked)
<anon: Main> (leaked) ---> <Main.second: Second> (indirectly leaked)

注意,second.reset()不一定会破坏指向的对象。它只需重置shared_ptr的本地实例如果这是指向该对象的最后一个实例,则该对象将被销毁,否则。。。没有什么