Custom deleters for std::shared_ptrs

2019-06-20 06:28发布

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?

2条回答
Bombasti
2楼-- · 2019-06-20 06:57

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
查看更多
地球回转人心会变
3楼-- · 2019-06-20 07:01

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.

查看更多
登录 后发表回答