Reputation: 614
Im starting learning about shared_ptr and weak_ptr. In theory everything looks simple. But when I started to testing, well... I have this really simple program:
#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;
}
The problem is, that Second is never deleted. Here is my output:
Program started Main created Second created Main deleted Program ended
Whats going on? I thought, that if I reset shared_ptr, and its last shared_ptr existing, object is deleting automatically.
Upvotes: 1
Views: 3776
Reputation: 300409
As I said, the situation is quite complicated, so I'll need a schema.
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()));
}
Right after the creation of main
, we have:
<anon: Second> (leaked)
<anon: Main> (leaked)
\
|---> <Main.second: Second>
/
<main: Main>
Note that main.second
is copied from <anon>.second
so, as those are shared_ptr<Second>
they both point to the same instance of Second
.
Then, main
dies, we are left with:
<anon: Second> (leaked)
<anon: Main> (leaked) ---> <Main.second: Second> (indirectly leaked)
Note that second.reset()
does not necessarily destroy the pointed-to object. It simply reset the local instance of shared_ptr
. If this was the last instance pointing to the object, then the object is destroyed, but otherwise... nothing.
Upvotes: 2
Reputation: 20609
You're initializing your shared pointers wrong. You don't need to use new
at all when using make_shared
. The parameters you pass to make_shared
are forwarded to the constructor of the class you're making.
So in your code, your make_shared
calls should look like this:
shared_ptr<Main> main = make_shared<Main>();
and
shared_ptr<Second> main = make_shared<Second>();
Instead, what you've done is leaked a version of each class (by using new explicitly and not deleting it) and then copied the leaked value into a second version. By splitting up the expression into multiple lines, we can more easily see what you've done wrong:
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.
Upvotes: 8