Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is a shared_ptr's deleter stored in memory allocated by the custom allocator?

Tags:

Say I have a shared_ptr with a custom allocator and a custom deleter.

I can't find anything in the standard that talks about where the deleter should be stored: it doesn't say that the custom allocator will be used for the deleter's memory, and it doesn't say that it won't be.

Is this unspecified or am I just missing something?

like image 370
Lightness Races in Orbit Avatar asked Nov 19 '19 11:11

Lightness Races in Orbit


Video Answer


1 Answers

util.smartptr.shared.const/9 in C++ 11:

Effects: Constructs a shared_ptr object that owns the object p and the deleter d. The second and fourth constructors shall use a copy of a to allocate memory for internal use.

The second and fourth constructors have these prototypes:

template<class Y, class D, class A> shared_ptr(Y* p, D d, A a); template<class D, class A> shared_ptr(nullptr_t p, D d, A a); 

In the latest draft, util.smartptr.shared.const/10 is equivalent for our purpose:

Effects: Constructs a shared_­ptr object that owns the object p and the deleter d. When T is not an array type, the first and second constructors enable shared_­from_­this with p. The second and fourth constructors shall use a copy of a to allocate memory for internal use. If an exception is thrown, d(p) is called.

So the allocator is used if there is a need to allocate it in allocated memory. Based on the current standard and at relevant defect reports, allocation is not mandatory but assumed by the committee.

  • Although the interface of shared_ptr allows an implementation where there is never a control block and all shared_ptr and weak_ptr are put in a linked list, there is no such implementation in practice. Additionally, the wording has been modified assuming, for instance, that the use_count is shared.

  • The deleter is required to only move constructible. Thus, it is not possible to have several copies in the shared_ptr.

One can imagine an implementation which puts the deleter in a specially designed shared_ptr and moves it when it the special shared_ptr is deleted. While the implementation seems conformant, it is also strange, especially since a control block may be needed for the use count (it is perhaps possible but even weirder to do the same thing with the use count).

Relevant DRs I found: 545, 575, 2434 (which acknowledge that all implementations are using a control block and seem to imply that multi-threading constraints somewhat mandate it), 2802 (which requires that the deleter only move constructible and thus prevents implementation where the deleter is copied between several shared_ptr's).

like image 91
AProgrammer Avatar answered Sep 27 '22 21:09

AProgrammer