shared_ptr.reset()不删除

时间:2013-08-04 12:48:47

标签: c++ c++11 shared-ptr

我开始学习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存在,那么对象就会自动删除。

2 个答案:

答案 0 :(得分:8)

您正在初始化您的共享指针错误。使用new时,您根本不需要使用make_shared。传递给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.

答案 1 :(得分:2)

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

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的本地实例。 如果这是指向该对象的最后一个实例,那么该对象将被销毁,但除此之外......没有。