C++ vector.reserve方法作用
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不會自動分配空間。