STD :: vector和std ::字符串重新分配策略

std::vector and std::string reallocation strategy

本文关键字:分配 策略 新分配 vector std 字符串 STD      更新时间:2023-10-16

在GCC的实现中,用于std :: string and std :: vector的重新定位策略是什么?

我对所采用的特定策略感兴趣:当我将项目附加到向量(或字符串字符串)时,它可能会超过保留的大小,然后将发生重新分配,但是新的大小将是一个函数的新尺寸旧的?在删除元素的情况下,实际重新分配和免费内存的门槛是什么(再次将是什么新尺寸)?

也将赞赏其他编译器的答案。

查看 bits/stl_vector.h中的函数 _M_check_len。它包含:

const size_type __len = size() + std::max(size(), __n);

因此,当您附加n元素的大小是最大者时,基本策略要么是大小的两倍或增加n。pop_back从不交易。libc (llvm)的做法完全相同。

阅读代码是您找到字符串,Deallocation等策略等唯一的方法。

vectorstring保证push_back的复杂性是"摊销常数",这意味着调用push_back n n 乘以分开的时间所需的时间n 被常数限制,因为 n 变大。实现此目的的唯一方法是使重新分配以几何形式增加尺寸,即使新容量成为旧大小的固定倍数。这样,您将只有非常"很少的"重新分离。

实施中的典型增长因素为2或1.5,尽管严格大于1的任何数字都会做。

这与reserve不相互作用。如果您在每次推回之前都会致电reserve(size() + 1),则每次都可以进行重新分配。

std :: vector具有方法的大小和容量。编写一个简单的程序来确定记忆分配的方式并不难。策略可能会随着每个实施的方式,甚至从版本到版本而发生变化。

我看到的一种策略是使用增加的增量,这是一种自适应策略:向饥饿的食物提供更多食物,以避免频繁的数据散发。但是增加的因素开放讨论。简单的重复可能会太快。

后来

好奇自己,我写了那个程序。这是输出(G 4.3.3):

capacity from 0 to 1 increased by 1 at size 1
capacity from 1 to 2 increased by 1 at size 2
capacity from 2 to 4 increased by 2 at size 3
capacity from 4 to 8 increased by 4 at size 5
capacity from 8 to 16 increased by 8 at size 9
capacity from 16 to 32 increased by 16 at size 17
capacity from 32 to 64 increased by 32 at size 33
capacity from 64 to 128 increased by 64 at size 65
capacity from 128 to 256 increased by 128 at size 129
capacity from 256 to 512 increased by 256 at size 257
capacity from 512 to 1024 increased by 512 at size 513
capacity from 1024 to 2048 increased by 1024 at size 1025
capacity from 2048 to 4096 increased by 2048 at size 2049
capacity from 4096 to 8192 increased by 4096 at size 4097
capacity from 8192 to 16384 increased by 8192 at size 8193
capacity from 16384 to 32768 increased by 16384 at size 16385
capacity from 32768 to 65536 increased by 32768 at size 32769
capacity from 65536 to 131072 increased by 65536 at size 65537
capacity from 131072 to 262144 increased by 131072 at size 131073
capacity from 262144 to 524288 increased by 262144 at size 262145
capacity from 524288 to 1048576 increased by 524288 at size 524289

使用构造函数中的初始分配会导致相同的进程,而不是1.

所有赌注都在上关闭了 reserve的工作原理。您使用这样的东西:

std::vector<T> myV;
myV.reserve(<space known to be needed>);

这样您就知道reserve不必被调用(也不需要进行任何重新分配),直到 超过该空间。