我刚刚开始学习向量,对size()
和capacity()
感到困惑
我对他们两个都知之甚少。但为什么这个程序都不同?偶数array(10)
为10个元素腾出空间并用0初始化。
添加array.push_back(5)
所以array.size();
是10即可。
所以array.capacity();
是10即可。
添加array.push_back(5)
所以array.size();
是11,即可(already 10 time 0 is added and then push_back add one more element 5 )
。
所以array.capacity();
是15为什么? ( is it reserving 5 blocks for one int? )
。
#include <iostream>
#include <vector>
int main(){
std::vector<int> array(10); // make room for 10 elements and initialize with 0
array.reserve(10); // make room for 10 elements
array.push_back(5);
std::cout << array.size() << std::endl;
std::cout << array.capacity() << std::endl;
return 0;
}
答案 0 :(得分:14)
标准规定std::vector<T>::push_back()
已经摊销O(1)
复杂度。这意味着扩展必须是几何的,即每次填充时存储量加倍。
简单示例:顺序push_back
32 int
成std::vector<int>
。您将存储所有这些,并且如果每次耗尽时将容量加倍,也会复制31份。为什么31?在存储第二个元素之前,复制第一个元素;在存储第3个之前,你复制元素1-2,在存储第5个之前,你复制1-4,等等。所以你复制1 + 2 + 4 + 8 + 16 = 31次,有32个商店。
进行正式分析表明,您获得O(N)
元素的N
个商店和副本。这意味着按O(1)
分摊push_back
复杂度(通常只有没有副本的商店,有时是商店和一系列副本)。
由于此扩展策略,您大多数时间都会size() < capacity()
。查找shrink_to_fit
和reserve
以了解如何以更细粒度的方式控制向量的容量。
注意:对于几何增长率,任何大于1的因子都可以,并且有一些研究声称1.5可以提供更好的性能,因为内存浪费较少(因为在某些时候重新分配的内存可以覆盖旧记忆。)
答案 1 :(得分:9)
这是为了提高效率,因此每次添加元素时都不必扩展基础数据结构。即每次都不必致电delete
/ new
。
答案 2 :(得分:5)
std::vector::capacity不是它的实际大小(由size()
返回),而是实际内部分配大小的大小。
换句话说,它是在需要另一次重新分配之前可以达到的大小。
每次执行push_back
时,为了不在每个插入的元素上调用新的重新分配(这是一个沉重的调用),它不会增加1。它保留更多,因为它不知道你之后是否不会做其他push_back
,在这种情况下,它不会为4更改分配的内存大小下一个元素。
在这里,4个下一个元素是1之间的折衷方案,它会最大限度地优化内存分配,但很快就会有另一个重新分配的风险,而且数量很大,这样可以让你快速地生成很多push_back
但是可以预留一个没有什么记忆。
注意:如果您想自己指定容量(例如,如果您知道矢量最大大小),则可以使用reserve成员函数执行此操作。
答案 3 :(得分:2)
使用
std::vector<int> array(10); // make room for 10 elements and initialize with 0
你实际用零填充了所有十个空格。添加广告附加元素将导致扩展容量,这要归功于效率。 在你的情况下,调用函数保留是没用的,因为你已经实例化了相同数量的元素。
答案 4 :(得分:1)
Size()
返回向量中的值。
并且capacity()
返回分配的存储容量大小意味着它现在可以容纳多少个值。
答案 5 :(得分:1)
我认为以下问题可以为您提供有关矢量容量的更多详细信息。
我将参考上述问题的答案。
capacity
的增长策略需要满足push_back
操作的摊销常数时间要求。然后,该策略旨在通常在空间不足时呈指数增长。简而言之,size
向量表示现在的元素数量,而captacity
表示其在将来用于push_back
的能力。