简体   繁体   English

std :: vector和std :: string重新分配策略

[英]std::vector and std::string reallocation strategy

What is the reallocation strategy used for std::string and std::vector in GCC's implementations? 在GCC的实现中,std :: string和std :: vector使用的重新分配策略是什么?

I'm interested in the specific strategy employed: When I append items to a vector (or chars to a string) it may exceed the reserved size and then a reallocation will occur, but what will be the new size as a function of the old one? 我对所采用的具体策略感兴趣:当我将项目附加到向量(或字符串的字符)时,它可能会超出保留的大小,然后会发生重新分配,但是新的大小将作为旧函数的函数。一? In case of deleting elements, what is the threshold to actually reallocate and free memory (and again what will be the new size)? 在删除元素的情况下,实际重新分配和释放内存的阈值是多少(再次是新大小)?

Answers for other compilers will be appreciated as well. 其他编译器的答案也将受到赞赏。

Look at the function _M_check_len in bits/stl_vector.h . 看功能_M_check_lenbits/stl_vector.h It contains: 它包含:

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

So the basic strategy when you append n elements is either double the size or increase by n, whichever is largest. 因此,附加n个元素时的基本策略是大小加倍或增加n,以最大者为准。 pop_back never deallocates. pop_back永远不会释放。 libc++ (LLVM) does exactly the same. libc ++(LLVM)完全相同。

Reading the code is the only way you'll find out the strategies for string, deallocation, etc. 阅读代码是您找到字符串,释放等策略的唯一方法。

Both vector and string guarantee that the complexity of push_back is "amortized constant", meaning that the time it takes to call push_back n times divided by n is bounded by a constant as n gets large. vectorstring保证push_back的复杂性是“分摊常量”,这意味着调用push_back n次除以n所花费的时间由n变大的常数限制。 The only way to achieve this is for the reallocation to increase the size geometrically, ie make the new capacity some fixed multiple of the old size. 实现这一目标的唯一方法是重新分配以几何方式增加大小,即使新容量成为旧大小的固定倍数。 That way you will only have very "few" reallocations. 这样你只需要很少的“重新分配”。

Typical growth factors in implementations are 2 or 1.5, though any number strictly greater than 1 will do. 实现中的典型增长因子是2或1.5,但任何严格大于1的数字都可以。

This doesn't interact with reserve , though. 但是,这不会与reserve相互作用。 If you call reserve(size() + 1) before each pushback, you may get a reallocation each time. 如果在每次回退之前调用reserve(size() + 1) ,则每次都可以重新分配。

All bets are off on how exactly reserve works. 所有的赌注都关闭上究竟如何 reserve工作。 You use it something like this: 你用它是这样的:

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

so you know reserve won't have to be called (nor any re-allocation performed) until after that space is exceeded. 所以你知道超过这个空间之前不必调用reserve (也没有执行任何重新分配)。

std::vector has methods size and capacity. std :: vector有方法大小和容量。 It should not be too difficult to write a simple program that determines the way memory allocations are being made. 编写一个确定内存分配方式的简单程序应该不会太困难。 Strategies may change with each implementation, and even from version to version. 策略可能会随着每个实现而变化,甚至可能随版本而变化。

One strategy I have seen is to use increasing increments, which is an adaptive strategy: give more food to the hungry to avoid frequent shuffles of the data. 我所看到的一个策略是使用递增的增量,这是一种自适应策略:为饥饿者提供更多食物以避免频繁改变数据。 But the factor of the increase is open to discussion. 但增加的因素可以讨论。 A simple duplication may grow too fast. 简单的复制可能会变得太快。

Later 后来

Curious myself, I wrote that program. 我很好奇,我写了那个程序。 Here is the output( g++ 4.3.3): 这是输出(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

Using an initial allocation in the constructor results in the same progression, using the initial value rather than 1. 在构造函数中使用初始分配会导致相同的进展,使用初始值而不是1。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM