std::allocator
is an abstraction over the underlying memory model, which wraps the functionality of calling new
and delete
. delete
doesn't need a size though, but deallocate() requires it.
void deallocate( T* p, std::size_t n );
"The argument n must be equal to the first argument of the call to allocate() that originally produced p; otherwise, the behavior is undefined."
Why?
Now I either have to make additional calculations before deallocating, or start storing the sizes that I passed to allocate. If I didn't use the allocator I wouldn't have to do this.
The design of the std::allocator
API - the Allocator
concept - is to facilitate the job of potential replacements.
std::allocator
is an abstraction over the underlying memory model
It doesn't have to be! In general, an allocator does not need to use C malloc
and free
, nor delete
or the not-in-place new
. Yes, the default one usually does it, but the allocator mechanism isn't merely an abstraction over C's memory model. To be different is often the whole purpose of a custom allocator. Remember that allocators are replaceable: a particular std::allocator
might not need the size for deallocation, but any replacements are likely to.
A compliant implementation of std::allocator
is free to assert that you indeed pass the correct n
to deallocate
, and to otherwise depend on the size being correct.
It happens that malloc
and free
store the chunk size in its data structures. But in general an allocator might not do it, and requiring it to do so is premature pessimization. Suppose you had a custom pool allocator and were allocating chunks of int
s. On a typical 64-bit system it'd be a 200% overhead to store a 64-bit size_t
along with the 32-bit int
. The user of the allocator is much better positioned to either store the size along in the allocation, or to determine the size in a cheaper fashion.
Good malloc implementations don't store allocation size for every small allocation; they and are able to derive the chunk size from the pointer itself e.g. by deriving a block pointer from the chunk pointer, and then inspecting the block header for the chunk size. That's but a detail of course. You could obtain the lower bound on the size using platform-specific APIs, such as malloc_size
on OS X, _msize
on Windows, malloc_usable_size
on Linux.
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