vector相关函数
-
size():vector当前拥有的元素个数
-
capacity():vector在必须分配新存储空间之前可以存储元素总数
创建完vector之后,size和capacity都为0,但是向vector插入元素之后,会发生变化,通常capacity大于等于size,这是vector内存增长机制决定的
-
push_back():向vector最后插入一个元素,在调用push_back时,若当前的capacity已经不能够放入新的元素(capacity=size),那么vector会重新申请一块内存,把之前内存里的元素拷贝到新的内存当中,然后把push_back的元素拷贝到新的内存中,最后要析构原有vector并释放原有内存,所以说这个过程效率是极低的,为了避免频繁的分配内存,C++每次申请内存都会成倍增长
-
reserve(a):vector预留空间a,但是空间内不真正创建对象(capacity=a,size=0),加入元素时,调用push_back或者insert函数,若添加元素没有超出预留,那么不会对内存进行重新分配。若加入的元素个数超过reserve的值,就会触发push_back的空间预留机制
-
resize(a, 0):改变vector的大小,创建对象(指定或默认为0,初始capacity=size=a),此时再调用push_back函数,新元素是加在新的空间后面,同样也会触发push_back的空间预留机制
vector类型提供resize操作来改变vector所包含的元素个数:如果当前vector长度大于新的长度值,则该vector后部的元素会被删除;如果当前vector长度小于新的长度值,则系统会在该vector后部添加新元素
reserve()和resize()的区别:
- reserve函数只有一个参数,即需要预留的空间;resize函数可以有两个参数,第一个参数是vector新的大小,第二个参数是要加入vector中的新元素,如果第二个参数省略,那么调用元素对象的默认构造函数
- 当不超过预留空间时,reserve不涉及内存重新分配,resize会涉及内存重新分配。但是如果是对空vector的操作,二者看不出区别
- reserve函数只修改capacity大小,不修改size大小
- resize函数既修改capacity大小,也修改size大小
-
clear(a):清空vector中的元素,vector所占用的内存空间依然存在,无法保证内存的回收。一维vector.clear(),清空一维的元素,保留着列的capacity;二维vector.clear(),清空各行的列,并回收列内存,保留行的capacity
-
a.swap(b):将a中的元素和b中的元素进行整体交换
- 利用swap去除vector多余的容量:vector< T >(x).swap(x);x是当前要操作的vector,T是类型
- 利用swap清空vector容器:vector< T >().swap(x)
vector内存增长的方式和特点
-
vector容器的capacity可以增加,不可以减少
当使用push_back、insert、emplace等成员函数的时候,可能会增加capacity;但是使用pop_back、erase、clear等成员函数的时候,并不会减少实际capacity,只是删除vector中的元素
-
向vector中新加入一个元素,比如使用push_back函数,当size大于capacity时,vector会重新找一块更大的内存,再把数据放进去。申请一块新的内存,把之前内存里面的元素拷贝到新内存中,把push_back的元素拷贝到新内存中,析构原有vector,释放原有内存
-
vector支持快速的随机访问,vector中的元素以连续方式存放。当向vector添加一个元素的时候,为了满足连续存放的特性,需要重新分配空间、拷贝元素、撤销旧空间,这样性能难以接受。STL底层对vector进行内存分配时,实际分配的capacity要比当前所需要的size要大一些,即预留了一些额外的存储区,用于存放新添加的元素,这样就不必为每个新元素重新分配整个容器的内存空间
vector定义与内存分配
-
类外定义
//一维vector vector<int> a(10); //二维vector vector<vector<int>> b(3, vector<int>(3, 0));
-
类中定义
不能使用以上类外两种定义方式
//一维vector,无法指定列长 vector<int> a{1, 2, 3}; //二维vector,无法指定列长 vector<int> b(3, vector<int>{1, 2, 3});
vector定义方式
-
一维vector
-
一开始知道列长
vector<int> a(3, 0);
-
一开始不知道列长,resize函数,实现按需分配
vector<int> b; b.resize(20);
-
一开始不知道列长,reverse函数和push_back函数,不建议使用,push_back函数可能带来内存溢出
vector<int> c; c.reserve(25); for (int i = 0; i < 25; i++) { c.push_back(i); }
-
-
二维vector(类中定义)
-
一开始知道行列信息,resize函数,按需分配
vector<vector<int>> d(5); for (int i = 0; i < d.size(); i++) { d[i].resize(10); }
当对空的vector采取resize,capacity=size
对于一个已有元素的vector进行resize,或者resize之后的vector,push_back了一些元素,那么会触发内存预留机制
-
vector清空元素与内存释放
-
vector的内存空间只增不减,初始化含有100个元素的vector,然后erase掉99个,留下一个有效元素,内存占用仍为100。内存空间是在vector析构时才被系统回收,同样使用clear之后,vector所占的内存空间依然不变
-
vector的内存空间只增加不减少,erase和clear只是减少了size,并不会减少capacity,所以内存空间没有减少,使用swap可以释放内存空间
-
vector()使用vector默认的构造函数建立临时vector对象,在该临时对象上调用swap成员,swap调用之后,原来的vector占用的空间就等于一个默认构造的对象的大小,临时对象就是原来对象的大小,而该临时对象随即就会被析构,从而占用的空间也被释放
//swap成员函数清空vector容器 vector<int>().swap(x); //构造的时候没有传递任何参数,意味着表达式调用的是vector模板类的默认构造函数,不是拷贝构造函数。生成一个空的vector,再借助swap函数将容器交换给x,清空x