1、vector中push_back操作
push_back的作用是在vector的末尾添加一个新元素。val的内容被复制(或移动)到新元素。
这有效地将容器大小增加1。当且仅当新的vector大小超过当前vector容量时,会重新自动分配新的存储空间。
Tips:
- std::vector::size()
vec.size()返回vec中元素的个数。 - std::vector::capacity()
vec.capacity()返回vec在内存中分配的空间大小。
push_back操作demo1:
//code1
#include <iostream>
#include <vector>
using namespace std;
#define MAX_NUM 9
int main(){
vector<int> vecInt;
for(int i = 0; i != MAX_NUM; i++){
vecInt.push_back(i);
}
/**
some code
*/
vecInt.push_back(123);
for(int i : vecInt){
cout << i << " ";
}
return 0;
}
// 0 1 2 3 4 5 6 7 8 123
以上代码先声明了一个存放int类型的vector,然后把i递增push_back到vecInt中。之后再添加一个元素到123到vecInt中。
push_back操作demo2:
iterator遍历vector
//code2
#include <iostream>
#include <vector>
using namespace std;
#define MAX_NUM 9
int main(){
vector<int> vecInt;
for(int i = 0; i != MAX_NUM; i++){
vecInt.push_back(i);
}
vector<int>::iterator iter = vecInt.begin();
cout << "the 1st element: " << *iter << endl;
vecInt.push_back(123);
while(iter != vecInt.end()){
cout << *iter << " ";
iter++;
}
return 0;
}
/*
the 1st element: 0
0 1 2 3 4 5 6 7 8 123
*/
在用for进行vector的push_back之后,初始化了一个iterator指向vecInt的begin位置,并打印验证。之后再用push_back在vector的末尾添加一个元素123,这时再用iter来遍历vecInt。
push_back操作demo3:
下面对MAX_NUM进行修改,将其改为8
//code3
#include <iostream>
#include <vector>
using namespace std;
#define MAX_NUM 8 //MAX_NUM修改为8,其余地方不做任何修改
int main(){
vector<int> vecInt;
for(int i = 0; i != MAX_NUM; i++){
vecInt.push_back(i);
}
vector<int>::iterator iter = vecInt.begin();
cout << "the 1st element: " << *iter << endl;
vecInt.push_back(123);
cout <<"vecInt's capacity: " << vecInt.capacity() << endl;
while(iter != vecInt.end()){
cout << *iter << " ";
iter++;
}
return 0;
}
/*
the 1st element: 0
vecInt's capacity: 16
-17891602 -17891602 -17891602 -17891602 -17891602 -17891602 -17891602 -17891602 -17891602 -17891602 -17891602 -17891602 -17891602 -17891602 -17891602 -17891602 -17891602 -17891602 -784369068 805499525 0 1 2 3 4 5
6 7 123
*/
只修改了MAX_NUM的值,其他一致。再次运行程序时,程序异常。
原因分析
对于vector来说,和数组最大的区别之一就是不需要在初始化的时候声明vector的大小。如果初始化的时候没有指明vector的大小,那么会根据实际的使用情况,在内存中为vector分配的大小分别2->4->8->16...
当MAX_NUM是8时,在for循环进行push_back之后,vecInt在内存中的大小为8。对vecInt再次将123进行push_back的时候,新的vector大小将超过当前的vector大小,所以会自动重新分配存储空间。
由于vector的存储空间已经被重新分配,在push_back123之后iter自然也就指向一个未知的空间,所以程序异常。
2、 vector的reserve的作用
为避免vector中在push_back过程中会进行内存的自动重新分配问题,vector提供了reserve函数。
reserve的作用时更改vector的容量,使vector至少可以容纳n个元素。
如果n大于vector当前的容量,reserve会对vector进行扩容,且当push_back的元素数量大于n的时候,会重新分配一个大小为2n的新空间,再将原有的n的元素放入新开辟的内存空间中。其他情况下都不会重新分配vector的存储空间。
Demo:对比使用reserve的区别
说明:在main中声明了两个vector,vecInt为默认初始化,vecIntB使用capacity初始化其容量为100。分别对vetIntA和vecIntB进行同样的操作:
①把0~99依次push_back到vector中,
②在push_back的过程中观察vector的容量capacity是否发生变化。
#include <iostream>
#include <vector>
#include <stdint.h>
using namespace std;
void growPushBack(vector<int> &vec, uint16_t size){
for(int i = 0; i < 100; i++){
vec.push_back(i);
if(size != vec.capacity()){
size = vec.capacity();
cout << "Capacity changed: " << size << endl;
}
}
}
int main(){
uint16_t sz = 0;
vector<int> vecIntA;
sz = vecIntA.capacity();
//声明vector后未使用reserve,直接进行push_back操作
cout << "Making vecIntA growing:" << endl;
growPushBack(vecIntA, sz);
cout << "\n========separator========\n" << endl;
vector<int> vecIntB;
sz = vecIntB.capacity();
//声明vecIntB后用reserve来执行其容量为100
vecIntB.reserve(100);
cout << "Making vecIntB growing: " << endl;
growPushBack(vecIntB, sz);
return 0;
}
/*
Making vecIntA growing:
Capacity changed: 1
Capacity changed: 2
Capacity changed: 4
Capacity changed: 8
Capacity changed: 16
Capacity changed: 32
Capacity changed: 64
Capacity changed: 128
========separator========
Making vecIntB growing:
Capacity changed: 100
*/
Demo运行结果分析:
如果一个vector使用默认的capacity,那么在push_back操作的时候,会根据添加元素的数量,动态的自动分配空间,2^n递增;如果声明vector的时候,显式的使用capacity(size_type n)来指定vector的容量,那么在push_back的过程中(元素数量不超过n),vector不会自动分配空间。