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不會自動分配空間。