Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does shared_ptr<void> know which destructor to use? [duplicate]

I wrote the following code to see how a shared_ptr<void> would behave when it is the last reference to a shared_ptr<Thing> and is itself destroyed.

#include <iostream> #include <string> #include <memory>  using namespace std;  struct Thing{     ~Thing(){         cout<<"Destroyed\n";     }     int data; };  int main(){     {         shared_ptr<void> voidPtr;         {             shared_ptr<Thing> thingPtr = make_shared<Thing>();             voidPtr = thingPtr;         }         cout<<"thingPtr is dead\n";     }     cout<<"voidPtr is dead\n";     return 0; } 

Which outputs:

thingPtr is dead Destroyed voidPtr is dead 

It behaves in a way I like, but it's totally unexpected and I'd like to understand what's going on here. The initial shared pointer no longer exists, it's just a shared_ptr<void> in the end. So I would expect this shared pointer to act like it's holding a void* and have no idea about Thing::~Thing(), yet it calls it. This is by design, right? How is the void shared pointer accomplishing this?

like image 772
Anne Quinn Avatar asked Aug 04 '19 07:08

Anne Quinn


People also ask

Why would you choose shared_ptr instead of Unique_ptr?

In short: Use unique_ptr when you want a single pointer to an object that will be reclaimed when that single pointer is destroyed. Use shared_ptr when you want multiple pointers to the same resource.

Can shared_ptr be copied?

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.

Does shared pointer call destructor?

When a shared_ptr object goes out of scope, its destructor is called. Inside its destructor it decrements the reference count by 1 and if new value of reference count is 0 then it deletes the associated raw pointer. To delete the internal raw pointer in destructor, by default shared_ptr calls the delete() function i.e.

What does the get () method of the shared_ptr class do?

std::shared_ptr::get Returns the stored pointer. The stored pointer points to the object the shared_ptr object dereferences to, which is generally the same as its owned pointer.


Video Answer


1 Answers

The shared state co-owned by shared pointers also contains a deleter, a function like object that is fed the managed object at the end of its lifetime in order to release it. We can even specify our own deleter by using the appropriate constructor. How the deleter is stored, as well as any type erasure it undergoes is an implementation detail. But suffice it to say that the shared state contains a function that knows exactly how to free the owned resource.

Now, when we create an object of a concrete type with make_shared<Thing>() and don't provide a deleter, the shared state is set to hold some default deleter that can free a Thing. The implementation can generate one from the template argument alone. And since its stored as part of the shared state, it doesn't depend on the type T of any shared_pointer<T> that may be sharing ownership of the state. It will always know how to free the Thing.

So even when we make voidPtr the only remaining pointer, the deleter remains unchanged, and still knows how to free a Thing. Which is what it does when the voidPtr goes out of scope.

like image 96
StoryTeller - Unslander Monica Avatar answered Oct 12 '22 11:10

StoryTeller - Unslander Monica