Since C++11, because of several reasons, developers tend to use smart pointer classes for dynamic lifetime objects. And with those new smart pointer classes, standards, even suggest to not use operators like new
instead they suggest to use make_shared
or make_unique
to avoid some error prone.
If we like to use a smart pointer class, like shared_ptr
, we can construct one like,
shared_ptr<int> p(new int(12));
Also we would like to pass a custom deleter to smart pointer classes,
shared_ptr<int> p(new int(12), deleter);
On the other hand, if we like to use make_shared
to allocate, for ex. int
, instead of use new
and shared_ptr
constructor, like on the first expression above, we can use
auto ip = make_shared<int>(12);
But what if we like to also pass a custom deleter to make_shared
, is there a right way to do that? Seems like compilers, at least gcc, gives an error to,
auto ip = make_shared<int>(12, deleter);
The deleter is part of the type of unique_ptr . And since the functor/lambda that is stateless, its type fully encodes everything there is to know about this without any size involvement. Using function pointer takes one pointer size and std::function takes even more size.
One reason is because make_shared allocates the reference count together with the object to be managed in the same block of memory. OK, I got the point. This is of course more efficient than two separate allocation operations.
So, if you throw exception from your class' constructor, then std::make_shared will throw it too. Besides exceptions thrown from constructor, std::make_shared could throw std::bad_alloc exception on its own.
std::make_sharedAllocates and constructs an object of type T passing args to its constructor, and returns an object of type shared_ptr<T> that owns and stores a pointer to it (with a use count of 1). This function uses ::new to allocate storage for the object.
As other have said, make_shared
cannot be used with a custom deleter. But I want to explain why.
Custom deleters exist because you allocated the pointer in some special way, and therefore you need to be able to deallocate it in a correspondingly special way. Well, make_shared
allocates the pointer with new
. Objects allocated with new
should be deallocated with delete
. Which the standard deleter dutifully does.
In short, if you can live with the default allocation behavior, you can live with the default deallocation behavior too. And if you can't live with the default allocation behavior, you should use allocate_shared
, which uses the provided allocator to both allocate and deallocate the storage.
Also, make_shared
is allowed to (and almost certainly will) allocate the memory for T
and the control block for the shared_ptr within the same allocation. This is something that your deleter can't really know about or deal with. Whereas allocate_shared
is capable of handling it, since the allocator you provide can do allocation and deallocation duties.
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