Why doesn't `std::string::reserve()` reserve exact amount of space I specify?
c++, memory-management, stdstring, stl
Solution
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 a `basic_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 of `reserve`. [ Note: Calling `reserve()` with a `res_arg` argument less than `capacity()` is in effect a non-binding shrink request. A call with `res_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.
Problem
`std::string::reserve()` doesn't allocate the exact amount of space I pass as argument. For example, if I try to reserve space for 100 characters, it reserves for 111 characters. If I pass 200, it reserves for 207. 655 for 650, 1007 for 1000. What is the reason behind this? Program code: ``` std::string mystr; std::cout << "After creation :" << mystr.capacity() << std::endl; mystr.reserve(1000); std::cout << "After reserve() :" << mystr.capacity() << std::endl; mystr = "asd"; std::cout << "After assignment :" << mystr.capacity() << std::endl; mystr.clear(); std::cout << "After clear() :" << mystr.capacity() << std::endl; ``` Code output: ``` After creation :15 After reserve() :1007 After assignment :1007 After clear() :1007 ``` (IDE: Visual Studio 2012)