Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 共享\u ptr.reset()未删除_C++_C++11_Shared Ptr - Fatal编程技术网

C++ 共享\u ptr.reset()未删除

C++ 共享\u ptr.reset()未删除,c++,c++11,shared-ptr,C++,C++11,Shared Ptr,我开始学习共享ptr和弱ptr。理论上,一切看起来都很简单。但是当我开始测试的时候。。。我有一个非常简单的程序: #include <iostream> #include <memory> using namespace std; class Second { public: Second() { cout << "Second created" << endl; } ~Second() {

我开始学习共享ptr和弱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;
}

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

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

因此,在代码中,make_共享调用应该如下所示:

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

相反,您所做的是通过显式使用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.

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

因此,在代码中,make_共享调用应该如下所示:

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

相反,您所做的是通过显式使用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.second是从.second复制的,因此,由于这些都是共享的,它们都指向second的同一个实例

然后,主模具,我们剩下:

<anon: Second> (leaked)

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

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

正如我所说,情况相当复杂,所以我需要一个模式

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.second是从.second复制的,因此,由于这些都是共享的,它们都指向second的同一个实例

然后,主模具,我们剩下:

<anon: Second> (leaked)

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

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

这是什么:共享*新秒;?在堆上创建一个对象,然后将其复制到另一个对象。原版永远不会被删除!相反,你应该这样做:让你分享@DeX3r您应该使用make_shared的参数来初始化一个构造函数需要参数的类。这是什么:make_shared*new Second;?在堆上创建一个对象,然后将其复制到另一个对象。原版永远不会被删除!相反,你应该这样做:让你分享@DeX3r你应该使用make_shared的参数来初始化一个构造函数需要参数的类。那么为什么我们也从来没有看到make_shared的Second实例被破坏?我一直相信亚洲程序员。。。不再是:P@quamrana:因为您没有重写Main的复制构造函数,所以第二个被复制。因此,当泄露主文件时,你也会泄露一个共享的文件:根据设计,在这个引用消失之前,不会发生删除,因为你泄露了它…@MatthieuM。啊!!谢谢fun首先泄漏一个Main,但是由于make_shared在那里也调用复制构造函数,所以它的成员second是默认构造的,因此即使未泄漏的Main被破坏,它的成员second也不保存任何内容,因此无论是重置调用还是second的破坏都不会调用我们正在寻找的析构函数。@SoapBox:No,他的描述不正确。Main的两个实例都指向同一个对象,因此Main.second指向的对象都不为null;然而,给定shared_ptr的语义,在两个句柄都被销毁之前,指向的对象不会被销毁。。。一个是在原来的主版本中泄露的。那么为什么我们也从来没有看到make_shared制作的第二个实例被破坏?我一直相信亚洲程序员。。。不再是:P@quamrana:因为您没有重写Main的复制构造函数,所以第二个被复制。因此,当泄露主文件时,你也会泄露一个共享的文件:根据设计,在这个引用消失之前,不会发生删除,因为你泄露了它…@MatthieuM。啊!!谢谢fun首先泄漏一个Main,但是由于make_shared在那里也调用复制构造函数,所以它的成员second是默认构造的,因此即使未泄漏的Main被破坏,它的成员second也不保存任何内容,因此无论是重置调用还是second的破坏都不会调用我们正在寻找的析构函数。@SoapBox:No,他的描述不正确。Main的两个实例都指向同一个对象,因此Main.second指向的对象都不为null;然而,给定shared_ptr的语义,指向的对象在两个句柄之前不会被销毁
都被摧毁了。。。其中一个泄漏在原来泄漏的主管道中。我也不需要第二个。重置;在主析构函数中,对吗?我的意思是,没有它它也可以工作,但它是正确的?我也不需要第二个。重置;在主析构函数中,对吗?我的意思是,没有它也能工作,但它是正确的吗?