The standard allows it
The C++ standard allows the implementation to reserve more memory than requested. In the standard (N3690, §21.4.4) it states
void reserve(size_type res_arg=0);
The member function
reserve()
is a directive that informs abasic_string
object of a planned change in size, so that it can manage the storage allocation accordingly.Effects: After
reserve()
,capacity()
is greater or equal to the argument ofreserve
. [ Note: Callingreserve()
with ares_arg
argument less thancapacity()
is in effect a non-binding shrink request. A call withres_arg <= size()
is in effect a non-binding shrink-to-fit request. — end note ]
The reason: Alignment on 16-byte boundaries
It seems that the reserved size is always a number that is a multiple of 16 minus one character for null termination. Memory reserved on the heap is always automatically 16-byte aligned on a x86 machine. Hence there is no cost in rounding up to the next biggest multiple of 16 for memory allocation.
The Microsoft documentation for malloc()
states that:
The storage space pointed to by the return value is guaranteed to be suitably aligned for storage of any type of object.
Objects of SIMD type must be 16-byte aligned to work best. These are packed types of 4 floats or 2 doubles (or other) that fit into the 128-bit registers of an x86 machine. If the data is not properly aligned, then loading and storing to these memory locations can lead a great loss of performance or even crashes. That's why malloc()
does this. Hence the conclusion for the 16-byte alignment. Most memory allocations (including operator new
) ultimately call malloc()
. Not allocating a multiple of 16 bytes would just be a waste of memory that would otherwise be unused anyways.