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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM