std :: string及其自动调整内存大小

时间:2010-08-24 14:35:16

标签: c++ string memory std dynamic-resizing

我对C ++很陌生,但我知道你不能像std :: string类那样只使用内存似乎让你这么做。例如:

std::string f = "asdf";
f += "fdsa";

字符串类如何处理变得越来越大?我假设它分配了一个默认的内存量,如果它需要更多,它new是一个更大的内存块,并将自身复制到它。但是,每次需要调整大小时,必须复制整个字符串并不是很低效吗?我真的不能想到可以做到的另一种方式(但显然有人这样做了)。

就此而言,所有stdlib类如vector,queue,stack等如何处理如此透明的增长和缩小?

3 个答案:

答案 0 :(得分:8)

您的分析是正确的 - 每次需要调整大小时, 都无法复制字符串。这就是为什么普通建议不鼓励使用模式的原因。使用字符串的reserve函数来要求它为打算存储在其中的内容分配足够的内存。然后进一步的操作将填补该内存。 (但如果你的提示结果太小,字符串也会自动增长。)

容器通常还会尝试通过分配比他们需要更多的内存来减轻频繁重新分配的影响。一种常见的算法是,当字符串发现它没有空间时,将其缓冲区大小加倍,而不是仅仅分配保存新值所需的最小值。如果字符串一次生成一个字符,则此倍增算法会将时间复杂度降低到分摊的线性时间(而不是二次时间)。它还降低了程序对内存碎片的敏感性。

答案 1 :(得分:7)

通常情况下,算法会加倍。换句话说,当它填充当前缓冲区时,它会分配一个两倍大的新缓冲区,然后复制当前数据。这导致分配/复制操作少于单个分配块增长的替代方案。

答案 2 :(得分:3)

虽然我不知道std :: string的确切实现,但大多数需要处理动态内存增长的数据结构都是按照你所说的去做 - 分配默认的内存量,如果需要更多,那么创建一个更大的块并复制自己。

解决明显的低效问题的方法是分配比你需要的更多的内存。已用内存的比率:向量/字符串/列表/等的总内存通常称为加载因子(也用于略有不同含义的哈希表)。通常它是1:2的比例 - 也就是说,你分配两倍于你需要的内存。当空间不足时,您可以为当前数量分配两倍的新内存并使用它。这意味着随着时间的推移,如果你继续向vector / string / etc添加东西,你需要越来越少地复制项目(因为内存创建是指数级的,你插入的新项目当然是线性的),所以这种内存处理方法所用的时间并不像你想象的那么大。根据{{​​3}}的原则,您可以看到使用此方法将m项插入向量/字符串/列表只是m的Big-Theta,而不是m 2