I realized that after calling vector.clear()
which hold shared pointers, the destructors of the object which own by shared_ptr
is not being released.
Code example can be seen below . Even vector.clear()
being called, destructor called after shared pointer goes beyond the scope.My question is - do I have to delete all smart pointers inside the vector manually by resetting them? Is there any easier way that you can advice ?
Output :
constructor
I am here
destructor
Code:
#include <vector>
#include <iostream>
#include <memory>
using namespace std;
class A
{
public:
A(){cout << "constructor" << endl;};
~A(){cout << "destructor" << endl;};
};
int main( )
{
shared_ptr<A> sharedptr (new A);
std::vector<shared_ptr<A> > test;
test.push_back(sharedptr);
test.clear();
cout << "I am here" << endl;
}
you have two copies of shared_ptr<A>
in this case, one is the sharedptr
variable and the other as an element in the vector.
do this instead
test.push_back(std::move(sharedptr));
note now the original sharedptr
has it's internal moved and no longer usable. The other thing is don't do anything at all, this is a perfectly valid usage of of shared_ptr and sharedptr
will clean up itself after it goes out of scope.
The problem arises when the push_back
adds a copy of the shared_ptr
to the vector, leaving the original dangling until main exists. If you don't make the shared_ptr in main scope, the problem does not happen. Just avoid making the shared_ptr in main scope. Make it as a temporary right in the push_back
call.
Output is now:
constructor
I am almost there
destructor
I am here
New code:
#include <vector>
#include <iostream>
#include <memory>
using namespace std;
class A
{
public:
A(){cout << "constructor" << endl;};
~A(){cout << "destructor" << endl;};
};
int main( )
{
vector<shared_ptr<A> > test;
test.push_back(shared_ptr<A>(new A));
cout << "I am almost there" << endl;
test.clear();
cout << "I am here" << endl;
return 0;
}
Here sharedptr and the element in vector share the same object which will result in invoking constructor and destructor only once.
The reason the destructor isn't called until later is that your variable sharedptr
is still in scope until the end of your main()
. There are a few ways around this if you really want it cleaned up before then. The most obvious way to fix this is to only use sharedptr
in a quick block scope:
int main( )
{
std::vector<shared_ptr<A> > test;
{
shared_ptr<A> sharedptr (new A);
test.push_back(sharedptr);
}
test.clear();
cout << "I am here" << endl;
}
Or alternatively, never create the sharedptr
variable at all:
int main( )
{
std::vector<shared_ptr<A> > test;
test.push_back( shared_ptr<A>(new A) );
test.clear();
cout << "I am here" << endl;
}