首先明确两个概念:
容量:capacity,是指容器在内存中获得的内存空间,容量100并不代表容器中就有100个元素,可能容器中只有10个,剩下的90个都是闲置的未定义内存空间。
大小:size,指容器中实际元素的个数,大小为100就代表容器就有100个已经存在的元素。
reserve():用来预留容量,但并不改变容器有效元素个数
resize():用来调整容器有效元素的个数,有时也会造成容量变大
reserve()函数原型:
void reserve(size_type n);
对于n值的大小,分两种情况:
(1)如果n大于容器现有的容量(capacity),比如你容器原来是100的容量,我现在指定n=200,那么就需要在自由内存区为整个容器重新分配一块新的更大的连续空间【因为vector是顺序容器,所以存储空间是连续的,如果之前的存储空间不够了,必须这样做】,然后将容器内所有的有效元素从旧位置全部复制到新位置,这个过程是调用拷贝构造函数,然后释放旧位置的所有存储空间,并调整容器的元素位置指示器。所以reserve的时候如果n比原来的大,结果只是让容器的冗余容量(即没有分配元素的存储区)变大,容器的实际大小,即元素个数并没有改变。
(2)如果n小于容器原来的容量,那么这个函数什么作用也没有了
resize()函数原型:
void resize(size_type n,const T& c = T());
其中n是要保留的元素个数,如果是要新增元素的话,c则是新增元素的默认初始值。
对于n值的大小,分三种情况:
(1)如果n大于容器当前的大小(即容器的size,这里和capacity无关),则在容器的末尾插入n-size()个初始值为c的元素;如果没有指定初始值,那就元素类型的默认构造函数来初始化。
(2)如果n小于容器当前的大小,则删除末尾的size()-n个元素,这样就导致容器的大小变了,size 变小了。但是这种类型的容器在删除一个元素的时候并不会释放元素本身的内存空间【这也是为了保留这块空间以避免将来要插入新元素的时候又要进行存储空间重分配】,所以容器的容量即capacity其实是没有改变的。
(3)n等于容器当前的大小,则什么也不做。
显然,reserve和resize的共同点就是:都不缩减容器本身的容量。即对内存空间并没有影响。那么要是当你觉得容器的容量太多的时候,应该如何缩减容量呢,这时候需要用到一个利用swap函数的技巧。
代码测试:
第一种情况:
reserve和resize中的n都大于当前容器所容纳元素的大小v.size()
#include
#include
using namespace std;
int main()
{
vector<int> vec={0,1,2,3,4,5,6,7,8,9};
vec.reserve(100);
vec.resize(50);
cout<<"the size of a: "<<vec.size()<<endl;
cout<<vec[8]<<endl;
for(auto e : vec)
cout<<e<<" ";
cout<<endl;
return 0;
}
输出结果:
第二种情况:
当reserve中n大于v.size,而resize中n小于n
#include
#include
using namespace std;
int main()
{
vector<int> vec={0,1,2,3,4,5,6,7,8,9};
vec.reserve(100);
vec.resize(5); //代码修改处
cout<<"the size of vec: "<<vec.size()<<endl;
cout<<vec[8]<<endl;
for(auto e : vec)
cout<<e<<" ";
cout<<endl;
return 0;
}
输出结果:
从结果可以看出,只输出了容器中前五个元素,说明当resize中n小于容器当前size时,会改变容器当前size。这里还有个小问题,在gcc编译环境下可以访问到vec[8]位置,理论上该位置不可访问。后来我在VS2022环境下测试发现,系统崩溃,访问不了vec[8]位置。出现这种差异,可能是gcc编译器原因。
第三种情况:
当reserve中n小于当前容器size的大小
#include
#include
using namespace std;
int main()
{
vector<int> vec={0,1,2,3,4,5,6,7,8,9};
vec.reserve(5); //代码修改处
vec.resize(50);
cout<<"the size of vec: "<<vec.size()<<endl;
cout<<vec[8]<<endl;
for(auto e : vec)
cout<<e<<" ";
cout<<endl;
return 0;
}