Is it possible to use a custom deleter after creating a std::shared_ptr
without using new
?
My problem is that object creation is handled by a factory class and its constructors & destructors are protected, which gives a compile error, and I don't want to use new
because of its drawbacks.
To elaborate: I prefer to create shared pointers like this, which doesn't let you set a custom deleter (I think):
auto sp1 = make_shared<Song>(L"The Beatles", L"Im Happy Just to Dance With You");
Or I can create them like this, which does let met set a deleter through an argument:
auto sp2(new Song, MyDeleterFunc);
But the second one uses new
, which AFAIK isn't as efficient as the top sort of allocation.
Maybe this is clearer: is it possible to get the benefits of make_shared<>
as well as a custom deleter? Would that mean having to write an allocator?
You have to use new
in your case as the design of std::make_shared
to avoid an additional allocation can only work if std::make_shared
can use it's own (internal) custom deleter to free to combined memory of the object and the shared_count
.
You have to accept that with your own custom deleter you can not optimize away an allocation, but you should still use a std::make_shared
-like wrapper to encapsulate the new
for reasons of safe usage. This helps to avoid memory leaks in cases where the constructors of the object throw an exception and someone uses
template<typename T>
void f(const T&, const T&);
f( std::shared_ptr<X>(new X), std::shared_ptr<X>(new X) ); // possible leak
instead of
std::shared_ptr<X> make_X() { return std::shared_ptr<X>(new X); }
f( make_X(), make_X() ); // no leak
No, there is no form of std::make_shared that takes a custom deleter.
If you need to return a shared_ptr
with a custom deleter then you'll have to take the performance hit.
Think about it: If you use make_shared
then it will allocate a larger memory region that can store the reference count and your object together, and the placement new will be called. The shared_ptr
returned from make_shared
already has a custom deleter, one that calls your object's destructor explicitly and then frees the larger memory block.