From the research I have done, it sounds like std::make_shared
is the preferred way of constructing a std::shared_ptr
. Specifically because:
new
, which performs at least two. My question is, assuming that I want a shared_ptr, should I always use make_shared
, or are there cases where new
is preferred?
make_shared is exception-safe. It uses the same call to allocate the memory for the control block and the resource, which reduces the construction overhead. If you don't use make_shared , then you have to use an explicit new expression to create the object before you pass it to the shared_ptr constructor.
One reason is because make_shared allocates the reference count together with the object to be managed in the same block of memory.
The difference is that std::make_shared performs one heap-allocation, whereas calling the std::shared_ptr constructor performs two.
Use shared_ptr if you want to share ownership of a resource. Many shared_ptr can point to a single resource. shared_ptr maintains reference count for this propose. when all shared_ptr's pointing to resource goes out of scope the resource is destroyed.
As the counter and the object share the same allocation, they also share the same deallocation.
The counter has to persist until the last shared_ptr
and weak_ptr
go away. If you have a large object (or many small objects) with long-lasting weak_ptr
s, this can cause memory contention if you allocate the shared_ptr
s via make_shared
.
Second, if you have a 3rd party API that hands you a pointer or a resource handle, and possibly has its own dispose functionality, make_shared
is neither appropriate nor possible to use in every case. Creating your own make_
functions can keep the messy details out of the way lets you deal with this problem, and deals with the exception corner case as well.
Finally, while shared pointers are awesome, they are also overly powerful. Quite often I want a unique_ptr
or even a boost::scoped_ptr
, or an intrusive reference counting pointer, or the like to represent ownership. shared_ptr
should be used only when the situation actually involves shared ownership of the resource: using it willy nilly because it is "easy" tends to end up with the resource equivalent of spaghetti code.
You may have to deal with legacy code which returns a dynamically allocated object. In which case, you would need to use the std::shared_ptr<T>
ctor with the pointer parameter. It's not preferable to using std::make_shared
but it does allow you to use all the std::shared_ptr<T>
goodness with legacy code.
I know that this is not strictly equivalent to using the std::shared_ptr<T>
ctor with new
directly but it is a valid use case of std::shared_ptr<T>
where make_shared
cannot be utilised.
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