调整大小并在向量中保留

resize and reserve in vector

主要问题

即使向量的容量大于其大小,resize 是否会影响性能?


比如我想做一个伪代码如下

const size_t size_a = 2;
const size_t i_max = 3;
vector<int> a(size_a) = random_vector;
vector<int> b;

for (size_t i=0; i<i_max; i++){
    patch_a_at_the_end_of_b;
}

所以,b 每次循环都会改变它的大小,但它会单调增加,我知道 b 的最终大小。


首先,我创建了一个函数 concat(a,b),以便将 a 补丁到 b 的末尾。

void concat(const vector<int> a, vector<int> &b){
    const size_t size_b = b.size();
    b.resize(size_b+a.size());
    for(size_t i=0; i<a.size(); i++)
        b[size_b + i] = a[i];
}

请注意,每次 concat 调用 b 时,我们都会调整向量的大小。

然后,我在主函数的for循环前面添加b.reserve

const size_t size_a = 2;
const size_t i_max = 3;
vector<int> a(size_a) = random_vector;
vector<int> b;
b.reserve(size_a*i_max);

for (size_t i=0; i<i_max; i++){
    concat(a,b);
}

std::vectors 操作的规范可能提供了这个问题的大部分答案。

首先,resize()被指定为void resize(size_type n, value_type val = value_type()),有要求;

  • 如果 n 小于当前大小,则移除并销毁附加元素(即,如果元素具有析构函数,则调用析构函数)。
  • 如果 n 大于当前容器大小,则通过在末尾插入所需数量的元素来扩展内容以达到 n 的大小。如果指定 val,则新元素被初始化为 val 的副本,否则,它们被值初始化。
  • 如果n也大于(强调我的)比当前容器容量,分配的自动重新分配存储 space 发生。

请注意,如果减小容器的大小,则不会减少容器容量。

现在,reserve(size_type n)被指定为要求向量容量n个或更多元素,要求

  • 如果 n 大于当前向量容量,则函数导致 容器重新分配其存储,将其容量增加到 n (或更大)。
  • 在所有其他情况下,函数调用不会导致重新分配,向量容量也不会受到影响。
  • 此函数对向量没有影响 size 并且不能改变它的元素。

这里的第二点可以理解为说reserve()不能用来减容

注:我在上面转述了,但它本质上是对resize()reserve()标准要求的总结。

将这些点放在一起:唯一需要resize()(或任何其他增加向量大小的操作)来增加向量容量的情况是新大小超过当前容量.

除此之外,发生的是实施质量问题。但是,一种合乎逻辑的实施方式是;

  • resize()(以及其他增加向量大小的操作)永远不会增加容量,除非新大小超过当前容量
  • reserve() 从不减少容量

在这样的实现中,在执行增加向量大小的操作之前调用 reserve() 会带来性能优势(消除实际重新分配的需要,除非大小增长到超过使用 [=22 指定的容量) =]).

如果实现使用不同的方法,例如在任何阶段减少容器的容量(例如,如果调用 resize() 减少大小,它也会减少容量),情况可能会有所不同。这样做可能是为了尽量减少容器的总内存使用量(即,只要 vector 本身存在,就不会保留分配的额外容量)。如果向量的大小波动(例如,在某些情况下增加,在其他情况下减少),这将对性能产生影响。