1

我开始学习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;
}

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

Program started
Main created
Second created
Main deleted
Program ended

这是怎么回事?我想,如果我重置 shared_ptr,并且它的最后一个 shared_ptr 存在,对象会自动删除。

4

2 回答 2

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.
于 2013-08-04T12:52:42.767 回答
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>

请注意,这是从somain.second复制的,因为它们都指向.<anon>.secondshared_ptr<Second>Second

然后,main死了,我们剩下:

<anon: Second> (leaked)

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

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

于 2013-08-04T17:37:14.797 回答