首先分清楚两个概念:

1.capacity:该值在容器初始化时赋值,指的是容器能够容纳的最大的元素的个数。还不能通过下标等访问,因为此时容器中还没有创建任何对象。

2.size:指的是此时容器中实际的元素个数。可以通过下标访问0-(size-1)范围内的对象。

就比如说一个瓶子的容量是600ml,意思是它最多可以装600ml,而不是说现在瓶子里就有600ml,这里的600ml就相当于capacity;而说现在瓶子的size为300ml,就是说它真的装有300ml。

那么就可以分清楚resize和reserve的区别了:

reserve是设置了capacity的值,比如reserve(20),表示该容器最大容量为20,但此时容器内还没有任何对象,也不能通过下标访问。

resize既分配了空间,也创建了对象,可以通过下标访问。当resize的大小

reserve只修改capacity大小,不修改size大小,resize既修改capacity大小,也修改size大小。

reserve是容器预留空间,但并不真正创建元素对象,在创建对象之前,不能引用容器内的元素,因此当加入新的元素时,需要用push_back()/insert()函数。

resize是改变容器的大小,并且创建对象,因此,调用这个函数之后,就可以引用容器内的对象了,因此当加入新的元素时,用operator[]操作符,或者用迭代器来引用元素对象。

再者,两个函数的形式是有区别的,reserve函数之后一个参数,即需要预留的容器的空间;resize函数可以有两个参数,第一个参数是容器新的大小,第二个参数是要加入容器中的新元素,如果这个参数被省略,那么就调用元素对象的默认构造函数。

这两个接口即存在差别,也有共同点。下面就它们的细节进行分析。
为实现resize的语义,resize接口做了两个保证:
一是保证区间[0, new_size)范围内数据有效,如果下标index在此区间内,vector[indext]是合法的。
二是保证区间[0, new_size)范围以外数据无效,如果下标index在区间外,vector[indext]是非法的。
reserve只是保证vector的空间大小(capacity)最少达到它的参数所指定的大小n。在区间[0, n)范围内,如果下标是index,vector[index]这种访问有可能是合法的,也有可能是非法的,视具体情况而定。
resize和reserve接口的共同点是它们都保证了vector的空间大小(capacity)最少达到它的参数所指定的大小。
因两接口的源代码相当精简,以至于可以在这里贴上它们:

  void resize(size_type new_size)
   { 
   		resize(new_size, T());
   }
  void resize(size_type new_size, const T& x)
   {
    	if (new_size < size()) 
      		erase(begin() + new_size, end()); // erase区间范围以外的数据,确保区间以外的数据无效
   		else
      		insert(end(), new_size - size(), x); // 填补区间范围内空缺的数据,确保区间内的数据有效
   }

如下例子:

#include<iostream>
#include<vector>
using namespace std;
int main()
{
    vector<int> a;
    cout<<"initial capacity:"<<a.capacity()<<endl;
    cout<<"initial size:"<<a.size()<<endl;

    /*resize改变capacity和size*/
    a.resize(20);
    cout<<"resize capacity:"<<a.capacity()<<endl;
    cout<<"resize size:"<<a.size()<<endl;


    vector<int> b;
     /*reserve改变capacity,不改变resize*/
    b.reserve(100);
    cout<<"reserve capacity:"<<b.capacity()<<endl;
    cout<<"reserve size:"<<b.size()<<endl;
return 0;
}

在这里插入图片描

需要注意的是:

对于resize:

如果n比当前的vector元素数目要小,vector的容量要缩减到resize的第一个参数大小,既n。并移除那些超出n的元素同时销毁他们。

如果n比当前vector元素数目要大,在vector的末尾扩展需要的元素数目,如果第二个参数val指定了,扩展的新元素初始化为val的副本,否则按类型默认初始化。

注意:如果n大于当前的vector的容量(是容量,并非vector的size),将会引起自动内存分配。所以现有的pointer,references,iterators将会失效。而内存的重新配置会很耗时间。

因此为了避免内存的重新配置,可以用reserve预留出足够的空间或者利用构造函数构造足够的空间。

参考:https://blog.csdn.net/jerry_SCY/article/details/79919989
https://blog.csdn.net/colddie/article/details/8665456

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐