I want to store shared pointers to the Object
class in a vector:
Test code:
#include <vector>
#include <iostream>
#include <memory>
using namespace std; // only for brevity
class Object
{
public:
int n;
Object(int n) : n(n) { cout << "Object(" << n <<")\n"; }
~Object() { cout << "~Object(" << n << "))\n"; n = 0xdddddddd; }
};
void Test()
{
std::shared_ptr<Object> p1(make_shared<Object>(Object(123)));
std::vector<shared_ptr<Object>> v;
cout << "before push_back\n";
v.push_back(std::make_shared<Object>(Object(2)));
v.push_back(p1);
cout << "after push_back\n";
cout << "Vector content:\n";
for (auto& p : v)
cout << " " << p->n << "\n"; ;
}
int main()
{
Test();
cout << "after Test()\n";
}
The output is
Object(123)
~Object(123)) <<< why is the destructor called here?
before push_back
Object(2)
~Object(2)) <<< why is the destructor called here?
after push_back
Vector content:
2
123
~Object(2)) <<< destructor called again
~Object(123))
after Test()
I don't understand why the destructors are called twice.
OTOH the vector content is what I want.
the last remaining shared_ptr owning the object is destroyed. the last remaining shared_ptr owning the object is assigned another pointer via operator= or reset().
All the instances point to the same object, and share access to one "control block" that increments and decrements the reference count whenever a new shared_ptr is added, goes out of scope, or is reset. When the reference count reaches zero, the control block deletes the memory resource and itself.
Use unique_ptr when you want to have single ownership(Exclusive) of the resource. Only one unique_ptr can point to one resource. Since there can be one unique_ptr for single resource its not possible to copy one unique_ptr to another. A shared_ptr is a container for raw pointers.
The ownership of an object can only be shared with another shared_ptr by copy constructing or copy assigning its value to another shared_ptr . Constructing a new shared_ptr using the raw underlying pointer owned by another shared_ptr leads to undefined behavior.
I don't understand why the destructors are called twice.
Because of creating unnecessary temporary objects here:
std::shared_ptr<Object> p1(make_shared<Object>(Object(123)));
^^^
temporary object
and here:
v.push_back(std::make_shared<Object>(Object(2)));
^^^
temporary object
It should instead be
std::shared_ptr<Object> p1(make_shared<Object>(123));
and
v.push_back(std::make_shared<Object>(2));
Why?
Because std::make_shared
constructs an object of type T and wraps it in a std::shared_ptr using args as the parameter list for the constructor of T. And in your code, you are making one extra object which immediately gets destroyed, thus calling the destructor.
Why don't you see Object(int n);
constructor being called for temporary object?
Object(int n);
constructor is indeed being called for the temporary object, but since the object held by the std::shared_ptr
is created through copy constructor (so, by copying the temporary object) you won't see call to Object(int n);
for it but call to Object(Object const& other);
.
In the demo, you can see first Object(int n);
constructor being called for the temporary object and then the call to copy constructor Object(Object const& other);
for the actual object being referenced by the std::shared_ptr
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With