c++performancestandardsallocatorc++23

Why allocate_at_least() in C++23?


According to cppref:

std::allocator<T>::allocate_at_least

Allocates count * sizeof(T) bytes of uninitialized storage, where count is an unspecified integer value not less than n, by calling ::operator new (an additional std::align_val_t argument might be provided), but it is unspecified when and how this function is called.

Then, this function creates an array of type T[count] in the storage and starts its lifetime, but does not start lifetime of any of its elements.

However, I think the already existing std::allocator<T>::allocate can do the same thing.

Why do we need std::allocator<T>::allocate_at_least in C++23?


Solution

  • allocate_at_least does not do the same thing as allocate. Compare (allocate):

    Allocates n * sizeof(T) bytes of uninitialized storage...

    with (allocate_at_least):

    Allocates count * sizeof(T) bytes of uninitialized storage, where count is an unspecified integer value not less than n...

    Moreover, allocate returns:

    Pointer to the first element of an array of n objects of type T...

    While allocate_at_least returns:

    std::allocation_result<T*>{p, count}, where p points to the first element of an array of count objects of type T...

    The caller thus gets the information about the actually allocated size.

    The motivation can be found in P0401R6; Section Motivation:

    Consider code adding elements to vector:

    std::vector<int> v = {1, 2, 3};
    // Expected: v.capacity() == 3
    
    // Add an additional element, triggering a reallocation.
    v.push_back(4);
    

    Many allocators only allocate in fixed-sized chunks of memory, rounding up requests. Our underlying heap allocator received a request for 12 bytes (3 * sizeof(int)) while constructing v. For several implementations, this request is turned into a 16 byte region.