为什么在 C++23 中 allocate_at_least()?

问题描述 投票:0回答:3

根据cppref

std::allocator<T>::allocate_at_least

分配

count * sizeof(T)
字节的未初始化存储,其中
count
是一个不小于
n
的未指定整数值,通过调用
::operator new
(额外的
std::align_val_t
论点可能是 提供),但未指定何时以及如何调用此函数。

然后,这个函数在存储中创建一个

T[count]
类型的数组 并开始其生命周期,但不开始其任何生命周期 元素。

但是,我认为已经存在的

std::allocator<T>::allocate
可以做同样的事情。

为什么在 C++23 中我们需要

std::allocator<T>::allocate_at_least

c++ performance standards allocator c++23
3个回答
20
投票

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

这就是

allocate_at_least
的目的,它的实现可能和
allocate
一样,也可能分配完全相同数量的元素,不同的是它能够返回分配给调用者的元素数量,这意味着如有必要,调用者可以使用这些额外的元素。


15
投票

allocate_at_least
allocate
不一样。比较(
allocate
):

Allocates

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

与(

allocate_at_least
):

Allocates

count * sizeof(T)
bytes of uninitialized storage,其中
count
是一个未指定的整数值,不小于
n
...

此外,

allocate
返回:

指向

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

allocate_at_least
返回时:

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

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

动机可见P0401R6;部分动机

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

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

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

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

3 * sizeof(int)
) 的请求。对于几个实现,这个请求变成了一个 16 字节的区域。


3
投票

这来自cppref的笔记:

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

“未指定时间和方式” 措辞使得组合或 优化标准库进行的堆外分配 容器,即使这种优化对于直接 调用 ::operator new。比如这个是libc++实现的

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

© www.soinside.com 2019 - 2024. All rights reserved.