【问题标题】:Why allocate_at_least() in C++23?为什么在 C++23 中 allocate_at_least()?
【发布时间】:2021-11-04 22:47:34
【问题描述】:

根据cppref

std::allocator<T>::allocate_at_least

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

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

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

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

【问题讨论】:

  • 我不确定,但我认为是为了提高内存分配和释放的效率。因为现在内存不需要完全等于请求的大小,它可以成为主内存页面大小的倍数(我猜?)。因此,我可以更轻松地分配或释放这些特定大小的内存。
  • 至少这个返回实际大小。不过,我不确定这是否是它存在的主要原因。

标签: c++ performance standards allocator c++23


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    allocate_at_leastallocate 做的事情不同。比较(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 指向count 类型T 类型的对象数组的第一个元素...

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

    动机可以在P0401R6; Section Motivation:

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

    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 字节的区域。

    【讨论】:

    • allocate::operator new 获取存储空间,允许过度分配。鉴于此,答案并不能真正解释实际差异。
    • @chris 好点,我相应地更新了答案。
    【解决方案3】:

    来自cppref的笔记:

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

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

    在调用 allocate_at_least 之后,在构造元素之前, T* 的指针算法在分配的数组中定义良好, 但是如果元素被访问,行为是不确定的。

    【讨论】:

    • 您的第二个强调部分并非特定于allocate_at_least。例如,相同的注释附加到allocate。您也可以将int main() { int* p = new int[5]; delete[] p; } 扔到 Clang 中,它也应该忽略它。
    猜你喜欢
    • 1970-01-01
    • 2021-07-25
    • 2023-01-23
    • 2017-08-04
    • 2021-12-05
    • 1970-01-01
    • 2021-12-05
    • 2021-09-21
    • 2022-11-27
    相关资源
    最近更新 更多