什么时候std :: vector重新分配它的内存数组?

时间:2011-03-23 18:42:53

标签: c++ stl vector

我找不到能给出明确答案的任何内容。我只是好奇如果std :: vector只在绝对必须时重新分配它的内部数组,或者它会在预期中提前重新分配(可以这么说)。

例如:

std::vector<int> myVector;
for (int i = 0; i < 1000; ++i) myVector.push_back(i);

cout << myVector.size() << '\n'      // Gives 1000 as expected
     << myVector.capacity() << endl; // Gives 1024 which makes sense

如果我继续添加元素,是否有可能我添加的下24个项目中的一个会改变容量,或者只有在我放入第25个项目后它才会重新分配?

注意:

我确实在Linux下使用gcc 4.4.3进行了测试,但似乎重新分配是“按需”完成的,但我很好奇我是不是很幸运,或者是否有某些地方说明这是预期的行为。

8 个答案:

答案 0 :(得分:16)

来自C ++标准23.2.4.2:

size_type capacity() const;
  

返回:向量可以容纳的元素总数,无需重新分配。

同样来自标准

  

注意:重新分配使引用中的元素的所有引用,指针和迭代器无效   序列。在调用之后发生的插入期间,保证不会发生重新分配   reserve()直到插入使向量的大小大于大小的时间   在最近一次调用reserve()中指定。

所以是的,你可以肯定。

编辑:正如@Bo Persson所提到的,有一个问题。如果我们从不致电reserve(),标准不会说什么。但是在实践中它运行良好,因为如果你调用reserve,没有实现会记住。我相信这是错误。正如@Martin在C ++ 0x草案中的回答中提到的那样,它已被纠正。

答案 1 :(得分:9)

来自标准:n3092:草案C ++ 0x

  

23.3.6.2载体容量[载体容量]

     

void reserve(size_type n);
  2效果:一种指令,通知向量计划的大小更改,以便它可以相应地管理存储分配。在reserve()之后,如果重新分配,capacity()大于或等于reserve的参数;并且等于capacity()的先前值。 当且仅当当前容量小于reserve() 的参数时,才会发生重新分配。如果抛出非CopyConstructible类型的移动构造函数以外的异常,则没有效果。

     

23.3.6.4向量修饰符[vector.modifiers]
  备注: 如果新大小大于旧容量 ,则会导致重新分配。如果没有重新分配,插入点之前的所有迭代器和引用仍然有效。如果除了复制构造函数之外抛出异常,移动构造函数,赋值运算符或T的移动赋值运算符,或者通过任何InputIterator操作都没有效果。如果非CopyConstructible T的移动构造函数抛出异常,则效果未指定。

答案 2 :(得分:6)

如果您查看cplusplus.com上的push_back文档,请说明:

  

这有效地增加了向量   大小一,导致一个   重新分配内部分配   存储,如果矢量大小相等   到之前的矢量容量   呼叫。重新分配使所有人失效   以前获得的迭代器,   引用和指针。

所以我非常怀疑在此之前尺寸会发生变化,但你可以随时测试它。至少在我的平台上,尺寸如上所述改变:

size vs capacity
1020 vs 1024
1021 vs 1024
1022 vs 1024
1023 vs 1024
1024 vs 1024
1025 vs 2048

答案 3 :(得分:2)

来自cplusplus.com

  

但是矢量也有容量,它决定了它们分配的存储空间量,并且可以等于或大于实际大小。不使用分配的额外存储量,但保留用于在其增长的情况下使用的向量。这样,向量不必在每次增长时重新分配存储,而只是在这个额外空间耗尽并且插入新元素时(这应该只发生在与其大小相关的对数频率上)。

答案 4 :(得分:2)

std :: vector会根据需求增加容量重新分配 - 即超出当前容量时(size() == capacity()时)。

将添加多少容量,具体取决于实现:通常为new_capacity = old_capacity * factor,其中factor介于1.5到2之间(理论上理想等于Golden section)。这样做是为了将新元素推回到向量中将分摊常量时间。

答案 5 :(得分:0)

标准保证哪些调用不会使迭代器失效。从技术上讲,std::vector只能通过执行不需要将数据复制到新位置的调整大小来符合标准,即不会使迭代器无效。不过,我怀疑是否有人这样做。

因此,调用reserve()resize()或任何其他被记录为使迭代器无效的调用都会发生调整。

答案 6 :(得分:0)

http://www.sgi.com/tech/stl/Vector.html

  

将重新分配内存   自动如果超过容量()    - 将size()元素插入向量中。重新分配没有   改变大小(),也不改变   向量的任何元素的值。   但它确实增加了容量(),   它使任何迭代器无效[5]   那指向矢量。

答案 7 :(得分:0)

我发现这些笔记很有帮助:

http://www.sgi.com/tech/stl/Vector.html#2

http://www.sgi.com/tech/stl/FAQ.html (为什么向量在执行重新分配时会将其存储扩展两倍?)

但是,这是SGI STL,找不到g ++文档。