Zizheng Tai
Zizheng Tai

Reputation: 6626

shared_ptr custom allocator together with custom deleter

Is it possible to use both a custom allocator and a custom deleter at the same time for std::shared_ptr? It seems to me that there is no way of doing so, since std::allocate_shared doesn't take a deleter. And also, the only sensible signature of the deleter would be something like void deleter(T*, const Alloc&), instead of just void deleter(T*).

Is there any way to work around this limitation?

Upvotes: 6

Views: 10551

Answers (2)

Kerrek SB
Kerrek SB

Reputation: 477150

Yes, you can do that, but make sure you understand what's going on. The deleter's purpose is to destroy the object. The allocator is used for internal book-keeping structures.

std::shared_ptr<T> sp(new T(args...), std::default_delete<T>(), myalloc);

The point of make_shared and allocate_shared is that they take care of constructing the object for you, so you don't specify a deleter — they use their own deleter that's appropriate for the way they obtained resources (i.e. respectively via operator new and the provided allocator).

You can of course create your own allocator deleter (like this one or the one proposed here) to pass into the above constructor to go along with an allocator-allocated object, and then also use the allocator (or a different one!) for the book-keeping.

There's something to be said for not using make_shared/allocate_shared in situations where either you have long-lived weak pointers or where binary size matters.

Upvotes: 7

Nicol Bolas
Nicol Bolas

Reputation: 473577

You can use a separate allocator and deleter; there are shared_ptr constructors that take both.

But you cannot do this through allocate_shared. The reason being that the allocator is for allocating/deallocating the shared storage. The deleter is for destroying the object being managed and freeing its storage.

Since allocate_shared allocates the object being managed in the same storage as the shared storage itself, it no longer makes sense for the two operations to be separate. And therefore, you must use the same object for both processes. The allocator allocates and deallocates the single allocation, and it takes care of construction/destruction duties for the T being created and destroyed.

Upvotes: 1

Related Questions