15

根据cppref

std::allocator<T>::allocate_at_least

通过调用 分配count * sizeof(T)未初始化存储的字节,其中 count是一个不小于 的未指定整数值(可能会提供附加参数),但未指定何时以及如何调用此函数。n::operator newstd::align_val_t

然后,此函数在存储中创建一个类型数组T[count]并开始其生命周期,但不开始其任何元素的生命周期。

但是,我认为已经存在的std::allocator<T>::allocate也可以做同样的事情。

为什么我们需要 std::allocator<T>::allocate_at_least 在 C++23 中?

4

3 回答 3

19

allocate可能会分配比请求更多的元素,但它无法将实际分配的大小返回给调用者。

这是 的目的allocate_at_least,它的实现可能allocate与分配完全相同数量的元素相同,不同之处在于它能够返回分配给调用者的元素数量,这意味着调用者可以使用那些额外的必要时的元素。

于 2021-09-08T07:27:02.713 回答
15

allocate_at_least不做同样的事情allocate。比较 ( allocate):

分配n * sizeof(T)未初始化存储的字节...

与(allocate_at_least):

分配count * sizeof(T)未初始化存储的字节,其中count是一个未指定的整数值,不小于n...

此外,allocate返回:

指向类型为...的n对象数组的第一个元素的指针T

虽然allocate_at_least返回:

std::allocation_result<T*>{p, count}, 其中p指向类型为...的对象数组的第一个元素countT

调用者因此获得有关实际分配大小的信息。

动机可以在P0401R6 中找到;部分动机

考虑将元素添加到向量的代码:

std::vector<int> v = {1, 2, 3};
// Expected: v.capacity() == 3

// Add an additional element, triggering a reallocation.
v.push_back(4);

许多分配器只分配固定大小的内存块,四舍五入请求。3 * sizeof(int)我们的底层堆分配器在构造 v 时收到了一个 12 字节的请求(

于 2021-09-08T07:17:46.867 回答
3

这来自cppref的注释:

allocate_at_least 主要用于连续容器,例如std::vector 和std::basic_string,以便通过尽可能使它们的容量与实际分配的大小匹配来减少重新分配。

未指定时间和方​​式”的措辞使得组合或优化由标准库容器进行的堆分配成为可能,即使直接调用 ::operator new 不允许此类优化。例如,这是由 libc++ 实现的。

在调用 allocate_at_least 和构造元素之前,T* 的指针算术在分配的数组中是明确定义的,但如果访问元素,则行为是未定义的。

于 2021-09-08T07:13:29.670 回答