我开始学习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存在,那么对象就会自动删除。
答案 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
的本地实例。 如果这是指向该对象的最后一个实例,那么该对象将被销毁,但除此之外......没有。