为什么在 C++23 中使用 allocate_at_least()?
Why allocate_at_least() in C++23?
根据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.
但是,我认为已经存在的 std::allocator<T>::allocate
可以做同样的事情。
为什么我们在 C++23 中需要std::allocator<T>::allocate_at_least
?
这来自cppref的笔记:
allocate_at_least is mainly provided for contiguous containers, e.g. std::vector and std::basic_string, in order to reduce reallocation by making their capacity match the actually allocated size when possible.
The "unspecified when and how" wording makes it possible to combine or
optimize away heap allocations made by the standard library
containers, even though such optimizations are disallowed for direct
calls to ::operator new. For example, this is implemented by libc++.
After calling allocate_at_least and before construction of elements,
pointer arithmethic of T* is well-defined within the allocated array,
but the behavior is undefined if elements are accessed.
allocate_at_least
与 allocate
不一样。比较 (allocate
):
Allocates n * sizeof(T)
bytes of uninitialized storage...
与 (allocate_at_least
):
Allocates count * sizeof(T)
bytes of uninitialized storage, where count
is an unspecified integer value not less than n
...
此外,allocate
returns:
Pointer to the first element of an array of n
objects of type T
...
同时 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
...
调用者因此获得有关实际分配大小的信息。
动机可以在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.
allocate
可能会分配比请求更多的元素,但它无法 return 向其调用者实际分配的大小。
这就是allocate_at_least
的目的,它的实现可能和allocate
一样,分配的元素数量可能完全一样,不同的是它能够return 分配给调用者的元素数量,这意味着调用者可以在必要时使用这些额外的元素。
根据cppref:
std::allocator<T>::allocate_at_least
Allocates
count * sizeof(T)
bytes of uninitialized storage, wherecount
is an unspecified integer value not less thann
, by calling::operator new
(an additionalstd::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.
但是,我认为已经存在的 std::allocator<T>::allocate
可以做同样的事情。
为什么我们在 C++23 中需要std::allocator<T>::allocate_at_least
?
这来自cppref的笔记:
allocate_at_least is mainly provided for contiguous containers, e.g. std::vector and std::basic_string, in order to reduce reallocation by making their capacity match the actually allocated size when possible.
The "unspecified when and how" wording makes it possible to combine or optimize away heap allocations made by the standard library containers, even though such optimizations are disallowed for direct calls to ::operator new. For example, this is implemented by libc++.
After calling allocate_at_least and before construction of elements, pointer arithmethic of T* is well-defined within the allocated array, but the behavior is undefined if elements are accessed.
allocate_at_least
与 allocate
不一样。比较 (allocate
):
Allocates
n * sizeof(T)
bytes of uninitialized storage...
与 (allocate_at_least
):
Allocates
count * sizeof(T)
bytes of uninitialized storage, wherecount
is an unspecified integer value not less thann
...
此外,allocate
returns:
Pointer to the first element of an array of
n
objects of typeT
...
同时 allocate_at_least
returns:
std::allocation_result<T*>{p, count}
, wherep
points to the first element of an array ofcount
objects of typeT
...
调用者因此获得有关实际分配大小的信息。
动机可以在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.
allocate
可能会分配比请求更多的元素,但它无法 return 向其调用者实际分配的大小。
这就是allocate_at_least
的目的,它的实现可能和allocate
一样,分配的元素数量可能完全一样,不同的是它能够return 分配给调用者的元素数量,这意味着调用者可以在必要时使用这些额外的元素。