I thought it is very curious when I discovered that the standard defines std::unique_ptr
and std::shared_ptr
in two totally different ways regarding a Deleter that the pointer may own. Here is the declaration from cppreference::unique_ptr and cppreference::shared_ptr:
template< class T, class Deleter = std::default_delete<T> > class unique_ptr; template< class T > class shared_ptr;
As you can see the unique_ptr "saves" the type of the the Deleter-object as a template argument. This can also be seen in the way the Deleter is retrieved from the pointer later on:
// unique_ptr has a member function to retrieve the Deleter template< class T, class Deleter = std::default_delete<T> > Deleter& unique_ptr<T, Deleter>::get_deleter(); // For shared_ptr this is not a member function template<class Deleter, class T> Deleter* get_deleter(const std::shared_ptr<T>& p);
Can someone explain the rational behind this difference? I clearly favor the concept for unique_ptr
why is this not applied to shared_ptr
aswell? Also, why would get_deleter
be a non-member function in the latter case?
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.
unique_ptr objects automatically delete the object they manage (using a deleter) as soon as they themselves are destroyed, or as soon as their value changes either by an assignment operation or by an explicit call to unique_ptr::reset.
unique_ptr is a new facility with a similar functionality, but with improved security. auto_ptr is a smart pointer that manages an object obtained via new expression and deletes that object when auto_ptr itself is destroyed.
Afterword. The flawless conversion of an std::unique_ptr to a compatible std::shared_ptr makes it possible to write efficient and safe factory functions. However, note that an std::shared_ptr cannot be converted to an std::unique_ptr.
Here you can find the original proposal for smart pointers: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1450.html
It answers your question quite precisely:
Since the deleter is not part of the type, changing the allocation strategy does not break source or binary compatibility, and does not require a client recompilation.
This is also useful because gives the clients of std::shared_ptr
some more flexibility, for example shared_ptr
instances with different deleters can be stored in the same container.
Also, because the shared_ptr
implementations needs a shared memory block anyhow (for storing the reference count) and because there alreay has to be some overhead compared to raw pointers, adding a type-erased deleter is not much of a big deal here.
unique_ptr
on the other hand are inteded to have no overhead at all and every instance has to embed its deleter, so making it a part of the type is the natural thing to do.
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