Thanks to std::make_shared
, I wonder, whether the constructor for std::shared_ptr
, which takes a raw pointer has any value except when interfacing with legacy / library code, e.g. when storing the output of a factory.
shared_ptr<T>::reset(T*)
?Regarding the code checks:
I know that interfacing with legacy / library code is quite common, so automated code checks might be problematic, but in most cases I encountered so far, I'd rather use a unique_ptr
anyway and I'm also not talking about a compiler warning that pops up at -Wall
, but rather about a rule for static code analysis during code review.
My motivation:
It is relatively easy to say "Don't use std::shared_ptr<T>(new T(...))
, always prefer std::make_shared<T>(...)
" (Which I believe is correct advise?). But I'm wondering if it isn't a design smell in general, if one has to create a shared_ptr
from a raw pointer, even - or especially - if the object was not just created via new
, because the object should have been created either as a "shared" or "unique" object in the first place.
First use case that pops to mind is when the deleter is not the default delete
.
E.g. in a windows environment COM objects must some times be used, the release of these objects must be done on the object itself, via Release
. Sure ATL can be used, but not everyone wants to use it.
struct ReleaseCom {
template <class T>
void operator() (T* p) const
{
p->Release();
}
};
IComInterface* p = // co created or returned as a result
std::share_ptr<IComInterface> sp(p, ReleaseCom());
A more uncommon situation - but still valid - is when an object (handle or even raw memory) is custom allocated in a dll, OS or library and has it's own associated cleanup function that must be called (which may or may not call delete
in turn). If memory allocation is involved std::allocate_shared
offers more enhanced control of the allocator that is to be used without exposing a raw pointer.
My personal feeling is that given std::make_shared
and std::allocate_shared
, the requirement to construct a shared_ptr
from raw pointers is becoming less and less. Even the cases above, can be wrapped into utility allocation and management functions, removing from the main business logic code.
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