Reputation: 99
As far as I know destructor is called when an element is erased from container, please correct me if I'm wrong..But Destr X prints shouldn't appear before after erase
#include <iostream>
#include <memory>
#include <vector>
struct X
{
X()
{
std::cout<<"Contr X"<<std::endl;
}
~X()
{
std::cout<<"Destr X"<<std::endl;
}
};
using Xptr = std::shared_ptr<X>;
int main()
{
std::shared_ptr<X> x = std::make_shared<X>();
Xptr x2 = std::make_shared<X>();
std::vector<Xptr> v;
v.emplace_back(x);
v.emplace_back(x2);
v.erase(v.begin());
std::cout<<"after erase\n";
return 0;
}
Upvotes: 1
Views: 819
Reputation: 48605
"As far as I know destructor is called when an element is erased from container..."
That is correct. But when that element is a std::shared_ptr
it is the std::shared_ptr
whose destructor is called, not the destructor of whatever the std::shared_ptr
is pointing to.
The std::shared_ptr
will only call the destructor of the object it points to if it is the last std::shared_ptr
pointing to it. But in your code you have 2
std::shared_ptr
s pointing to each of the objects you created. You have one each in the std::vector
and one each as local std::shared_ptr
variables x
and x2
before they are added to the std::vector
.
So when you delete the elements from the std::vector
the std::vector
delets the std::shared_ptr
s it contains but the objects pointed to by those std::shared_ptr
s are not destroyed until the std::shared_ptr
variables x
and x2
go out of scope at the end of main()
.
Upvotes: 1
Reputation: 74018
Since you use a shared_ptr
, you have two references to both objects. These are x
and x2
, and the shared_ptr
s inside vector v
.
When you erase()
, the destructor of shared_ptr
is called, and the reference count is decremented, but still 1
. Therefore object X
still exists.
After leaving the scope of main()
, the count is decremented again. Now the count goes down to zero, and the destructor of object X
is called.
Hence the output "after erase" is shown first, and only then "Destr X".
When you put x
and x2
in an inner scope, you will see the expected behaviour
std::vector<Xptr> v;
{
std::shared_ptr<X> x = std::make_shared<X>();
Xptr x2 = std::make_shared<X>();
v.emplace_back(x);
v.emplace_back(x2);
}
std::cout<<"before erase\n";
v.erase(v.begin());
std::cout<<"after erase\n";
Now you see
Contr X
Contr X
before erase
Destr X
after erase
Destr X
Upvotes: 1