1. 程式人生 > 其它 >C++ STL :Vector記憶體分配與釋放

C++ STL :Vector記憶體分配與釋放

技術標籤:c++/CLI

vector 可以容納許多型別的資料,如若干個整數,所以稱其為容器。

vector 是C++ STL的一個重要成員,使用它時需要包含標頭檔案:#include<vector>

關於vector的使用,雖然可以動態的分配記憶體,但是稍不注意,就會落入記憶體陷阱中,無形中增大了程式的記憶體開銷,導致程式崩潰。基於此,有必要梳理一下C++ STL中的vector的記憶體分配與釋放機制。

文章從“定義”、“新增”、“清空”三個部分來探究vector的記憶體分配和釋放機制。

導讀:

1. vector記憶體相關介紹

  • size(),capacity(),push_back(),reserve(),resize(),clear(),swap()
  • vector記憶體增長特點

2. vector定義與記憶體分配

  • 類中定義 & 類外定義(包括全域性、主函式、類成員函式、自定義函式等)
  • 一維vector & 二維vector
  • 空vector & 指定行vector & 指定行列vector

3. vector定義方式建議

4. vector清空元素與記憶體釋放

  • clear()
  • swap()
以下是正文,測試程式碼會放在最後。

1. vector記憶體相關介紹

1.1 相關函式

(1)b.size():容器當前擁有的元素個數。

(2)b.capacity():容器在必須分配新儲存空間之前可以儲存的元素總數。

區別:建立完空vector後,其size和capacity都為0,但是向vector插入元素後,會發生變化,通常capacity大於等於size,這是vector記憶體增長機制決定的。

(3)b.push_back():在向量最後插入一個元素。在呼叫push_back時,若當前容量已經不能夠放入新的元素(capacity=size),那麼vector會重新申請一塊記憶體,把之前的記憶體裡的元素拷貝到新的記憶體當中,然後把push_back的元素拷貝到新的記憶體中,最後要析構原有的vector並釋放原有的記憶體。所以說這個過程的效率是極低的,為了避免頻繁的分配記憶體,C++每次申請記憶體都會成倍的增長。

(4)b.reserve(a):容器預留空間a,但在空間內不真正建立元素物件(capacity=a,無size)。所以在沒有新增新的物件之前,不能引用容器內的元素。加入元素時,要呼叫push_back()/insert()函式,值得一提的是,若新增元素沒有超出預留,那麼是不會對記憶體進行重新分配的

。此外,若加入元素超出了reserve()的值,是可以繼續新增的,但是此時就會觸發push_back()的空間預留機制。

(5)b.resize(a,0):改變容器的大小,且建立物件(指定或預設0,初始capacity = size = a)。因此,呼叫這個函式之後,可以引用容器內的物件了,因此當加入新的元素時,用operator[]操作符,或者用迭代器來引用元素物件。此時再呼叫push_back()函式,是加在這個新的空間後面的。同樣也會觸發push_back()的空間預留機制。

容器型別提供resize操作來改變容器所包含的元素個數:如果當前的容器長度大於新的長度值,則該容器後部的元素會被刪除;如果當前的容器長度小於新的長度值,則系統會在該容器後部新增新元素。

需要注意的是:resize操作可能會使迭代器失效,對於所有的容器型別,如果resize操作壓縮了容器,則指向已刪除的元素的迭代器失效。

區別:

  • reserve函式只有一個引數,即需要預留的容器的空間;resize函式可以有兩個引數,第一個引數是容器新的大小, 第二個引數是要加入容器中的新元素,如果這個引數被省略,那麼就呼叫元素物件的預設建構函式。
  • 當不超過預留空間時,reserve()不涉及記憶體的重新分配,resize()會涉及記憶體的重新分配。但是如果是對空容器操作,那麼二者看不出內在的區別。
  • reserve()只修改capacity大小,不修改size大小,
  • resize()既修改capacity大小,也修改size大小。

(6)b.clear():清空向量中的元素。但是即使clear(),vector所佔用的記憶體空間依然如故,無法保證記憶體的回收。一維vector.clear(),清空一維的元素,但是仍舊保留著列的capacity;二維vector.clear(),清空各行的列,並且回收列記憶體capacity,但是保留行的capacity

(7)a.swap(b):將a中的元素和b中的元素進行整體性交換。除此之外,①可以利用swap()方法去除vector多餘的容量:vector<T>(x).swap(x);其中,x是當前要操作的容器,T是容器的型別。②利用swap()方法清空vector容器:當 swap() 成員方法用於清空 vector 容器時,可以套用如下的語法格式:vector<T>().swap(x)

1.2 vector記憶體增長策略和特點

(1)vector的容器的大小隻可以增加,不可以減少。當我們使用push_back() , insert() , emplace()等成員方法的時候,有可能會增加容量,但是我們使用 pop_back()、erase()、clear() 等方式的時候,並不會減少實際 的記憶體容量。只是可以刪除容器裡面的內容。

(2)vector 有一個機制是這樣的,如果新加入一個元素,比如通過push_back(),但是size 大於了capacity,那麼vector 就會重新找一塊更大的地方再把資料放進去。重新分配的過程:申請一塊新的記憶體 > 拷貝資料 > 釋放原記憶體

所以,使用vector容器的時候可以預先空間,把capacity定得夠大,這樣可以儘量避免重新分配vector 的記憶體,不增加程式的負擔。即:reserve()預留空間+push_back()壓入元素+size()控制讀取的策略,但是還是不推薦這麼用,原因後面解釋。

(3)綜合來看,vector為了支援快速的隨機訪問,vector容器的元素以連續方式存放,每一個元素都緊挨著前一個元素儲存。設想一下,當vector新增一個元素時,為了滿足連續存放這個特性,都需要重新分配空間、拷貝元素、撤銷舊空間,這樣效能難以接受。因此STL實現者在對vector進行記憶體分配時,其實際分配的容量要比當前所需的空間多一些。就是說,vector容器預留了一些額外的儲存區,用於存放新新增的元素,這樣就不必為每個新元素重新分配整個容器的記憶體空間。

在呼叫push_back時,每次執行push_back操作,相當於底層的陣列實現要重新分配大小;這種實現體現到vector實現就是每當push_back一個元素,都要重新分配一個大一個元素的儲存,然後將原來的元素拷貝到新的儲存,之後在拷貝push_back的元素,最後要析構原有的vector並釋放原有的記憶體。

2. vector定義與記憶體分配

2.1 類中定義 & 類外定義

vector在類中私有/公有成員中的定義方式居然和全域性、函式內的定義方式還有所區別,具體原因也沒了解到(和預設建構函式有關),總之用這玩意兒到處都是坑,吐。

(1)類外定義(圓括號)

一維vector

vector<int>a(10);

二維vector

vector<vector<int>>c(5, vector<int>(10));

以上定義都是有初始值的,所以可以直接用下標訪問。舉例的是已知一些行列資訊的定義方式,其餘的定義方式在下面說,差不多。

(2)類中定義{花括號}

不能使用以上類外的兩種定義方式。

一維vector:無法指定列長,可以用花括號{ }初始化列元素。

vector<int>a1{ 1,2,3 };

二維vector:可以用花括號{ }指定行數,無法指定列長,但可以用花括號{ }初始化列元素。

vector<vector<int>>c{ N };
vector<vector<int>>d1{ N ,vector<int> {1,2,3} };

只要vector中沒有定義列長,那麼就是個空的容器。具體細節見下程式碼:

class Vector_define
{
private:
	int i, j;
	/*一維vector*/
	//vector<int>a(N);				/*在自定義類中無法對vector實現圓括號()初始化長度的定義*/
	vector<int>a{ N };				/*此種花括號{}的初始化可以定義。作用:只是輸入一個元素,而非定義長度*/
	vector<int>a1{ 1,2,3 };			/*支援直接輸入元素*/
	vector<int>b;					/*正常定義,空的,無長度*/
	
	/*二維vector*/
	//vector<vector<int>>c(N, vector<int>(T));			/*該種定義同一維,無效定義*/
	vector<vector<int>>c{ N };							/*二維vector該種花括號{}定義有效。作用:佔行,而非輸入元素,這和一維不一樣*/
	//vector<vector<int>>c{ 1,2,3 };					/*無效定義*/
	vector<vector<int>>d{ N ,vector<int> {T} };			/*該種定義,支援行定義,不支援列定義,但支援行新增*/
	vector<vector<int>>d1{ N ,vector<int> {1,2,3} };	/*支援行直接輸入元素,且是為每一行都插入*/
	vector<vector<int>>e;								/*正常定義,空的,無長度*/
}

3. vector定義方式建議

經過以上的一些探索,在這對不同vector定義方式的記憶體變化再做出一些分析和建議。

(1)一維vector

①一開始知道列長。

vector<int>a(10);

②一開始不知道列長,resize()策略。

vector<int>c;
...
c.resize(25);

優點:按需分配,有初始值,可以用下標直接改值。

③一開始不知道列長,reserve()+push_back()策略。

vector<int>a;
...
a.reserve(25);
for (i = 0; i < 25; i++)
{
	a.push_back(i + 1);
}

缺點:不建議用,雖然也是按需分配,但是由於push_back()可能帶來記憶體溢位。

(2)二維vector(以類中定義為例)

①一開始知道行、列資訊的,resize()策略。

vector<vector<int>>h(5);
for (i = 0; i < h.size(); i++)
{
	h[i].resize(10);
}

當對空vector採取resize(),capacity=size,但如果是對一個已有元素的vector進行resize(),或者是又對resize後的vector,push_back了一些元素,那麼就會觸發記憶體預留機制,所以如果要想去除多餘的空間,可以採用如下方法:

vector<int>(h).swap(h)

優點:按需分配,有初始值,可以用下標直接改值。

②一開始知道行、列資訊的,reserve()+push_back()策略。

不推薦!!!原因如下:

1)因為但凡用到push_back(),如果忘記清空,稍不注意,在某些迴圈中,迴圈一次就壓入一堆元素,不光影響資料的使用,而且還會不停擴張記憶體,更嚴重的是當用完預留的記憶體後,更是成倍的開闢記憶體空間,直逼程式崩潰。

2)即便是記得使用清空的策略去除無關的元素,也容易錯誤的使用清空方式。比如:

vector<vector<int>> b{ N };
for (i = 0; i < N; i++)
{
	b[i].reserve(T);
}

該二維vector在定義時,已經指定了行數,所以“b.clear()”的行為是錯誤的,而“b[0],clear()”才是正確的,也即只能清空列。

又或者你想這樣定義(錯誤!):

vector<vector<int>> e;
e.reserve(10);
for (i = 0; i < N; i++)
{
	b[i].reserve(10);
}

看著沒問題,實際是個錯誤的定義。若一開始沒有定義行,那麼是無法通過reserve()固定行的;只能通過resize()的方式。

總結起來就是,這種策略的定義方式,特別容易出錯!

③其他的情況暫且不論,總之能用resize()就用,能不用push_back()就不用,一旦用了,根據情況,需要清空的一定要正確及時的清空,避免記憶體損耗和溢位!

4. vector清空元素與記憶體釋放

由於vector的記憶體佔用空間只增不減,比如你首先分配了10,000個位元組,然後erase掉後面9,999個,留下一個有效元素,但是記憶體佔用仍為10,000個。所有記憶體空間是在vector析構時候才能被系統回收。empty()用來檢測容器是否為空的,clear()可以清空所有元素。但是即使clear(),vector所佔用的記憶體空間依然如故,無法保證記憶體的回收。

就像前面所說的,vector的記憶體空間是隻增加不減少的,我們常用的操作clear()和erase(),實際上只是減少了size(),清除了資料,並不會減少capacity,所以記憶體空間沒有減少。那麼如何釋放記憶體空間呢,正確的做法是swap()操作。

swap交換技巧實現記憶體釋放思想:vector()使用vector的預設建構函式建立臨時vector物件,再在該臨時物件上呼叫swap成員,swap呼叫之後原來vector佔用的空間就等於一個預設構造的物件的大小,臨時物件就具有原來物件v的大小,而該臨時物件隨即就會被析構,從而其佔用的空間也被釋放。

當 swap() 成員方法用於清空 vector 容器時,可以套用如下的語法格式:

vector<T>().swap(x);

這裡沒有為 vector<T>() 表示式傳遞任何引數。這意味著,此表示式將呼叫 vector 模板類的預設建構函式,而不再是複製建構函式。也就是說,此格式會先生成一個空的 vector 容器,再借助 swap() 方法將空容器交換給 x,從而達到清空 x的目的。

完整測試程式碼:

#include<iostream>
using namespace std;
#include<vector>

#define N 20
#define T 10

/*類Vector_define:探究在類中對vector進行定義的特點*/
class Vector_define
{
private:
	int i, j;
	/*一維vector*/
	//vector<int>a(N);				/*在自定義類中無法對vector實現圓括號()初始化長度的定義*/
	vector<int>a{ N };				/*此種花括號{}的初始化可以定義。作用:只是輸入一個元素,而非定義長度*/
	vector<int>a1{ 1,2,3 };			/*支援直接輸入元素*/
	vector<int>b;					/*正常定義,空的,無長度*/
	
	/*二維vector*/
	//vector<vector<int>>c(N, vector<int>(T));			/*該種定義同一維,無效定義*/
	vector<vector<int>>c{ N };							/*二維vector該種花括號{}定義有效。作用:佔行,而非輸入元素,這和一維不一樣*/
	//vector<vector<int>>c{ 1,2,3 };					/*無效定義*/
	vector<vector<int>>d{ N ,vector<int> {T} };			/*該種定義,支援行定義,不支援列定義,但支援行新增*/
	vector<vector<int>>d1{ N ,vector<int> {1,2,3} };	/*支援行直接輸入元素,且是為每一行都插入*/
	vector<vector<int>>e;								/*正常定義,空的,無長度*/

public:
	void test1()
	{
		/*teat a*/
		cout << "a.size()=" << a.size() << endl;	/* a.size()=1 ,可知類中花括號只是添加了元素而已*/
		for (i = 0; i < a.size(); i++)
		{
			cout << a[i] << "  ";					/* 只輸出 20 ,也即只有一個元素*/
		}
		cout << endl << endl;
		
		/*teat b*/
		cout << "b.size()=" << b.size() << endl;	/* b.size()=0 ,沒有元素,正常*/
		/*for (i = 0; i < a.size(); i++)
		{
			cout << b[i] << "  ";					// 報錯:out of range! 空的容器,沒有長度,沒有東西輸出!
		}
		cout << endl ;*/
		cout << endl;

		/*teat c*/
		cout << "c.size()=" << c.size() << endl;	/* c.size()=20,可知二維vector支援花括號{}定義行數 */
		for (i = 0; i < c.size(); i++)
		{
			for (j = 0; j < c[i].size(); j++)
			{
				cout << c[i][j] << "  ";			/* 不報錯,有行沒列,輸出不了什麼, */
			}
			cout << endl;
		}
		cout << endl;

		/*teat d*/
		cout << "d.size()=" << d.size() << endl;	/* d.size()=20,花括號{}行定義仍舊有效 */
		for (i = 0; i < d.size(); i++)
		{
			cout << "d[" << i << "].size()=" << d[i].size() << "  ";
		}											/* d[i].size()=1,可知花括號{}列長定義無效 */
		cout << endl;
		for (i = 0; i < d.size(); i++)
		{
			for (j = 0; j < d[i].size(); j++)
			{
				cout << d[i][j] << "  ";			/* d[i][j]=T,可知花括號{}列長定義無效,只是添加了一個元素 */
			}
			cout << endl;
		}
		cout << endl;

		/*teat e*/
		cout << "e.size()=" << e.size() << endl;	/* e.size()=0,行0,列空 */
		for (i = 0; i < e.size(); i++)
		{
			cout << "e[" << i << "].size()=" << e[i].size() << "  ";
		}											/* 列空 */
		cout << endl;
		for (i = 0; i < e.size(); i++)
		{
			for (j = 0; j < e[i].size(); j++)
			{
				cout << e[i][j] << "  ";			/* 容器空 */
			}
			cout << endl;
		}
		cout << endl;
	}
};
/*類Vector_memory:探究在類中定義的vector的記憶體特點*/
class Vector_memory
{
private:
	int i, j;
	/*一維*/
	vector<int>a;
	vector<int>b{ 1,2,3 };
	vector<int>c;
	vector<int>d;
	
	/*二維*/
	vector<vector<int>>e;
	vector<vector<int>>f{ N };
	vector<vector<int>>g{ N,vector<int>{1,2,3} };

public:
	void test2()
	{
		/*一維記憶體*/
		cout << "a.capacity()=" << a.capacity() << endl;	/* a.capacity()=0 */
		cout << "a.size()=" << a.size() << endl << endl;	/* a.capacity()=0 */
	
		cout << "b.capacity()=" << b.capacity() << endl;	/* a.capacity()=3,不會預留空間*/
		cout << "b.size()=" << b.size() << endl << endl;	/* a.capacity()=3 */
	
		//①往 a 中新增元素:研究 pushback() 對記憶體的改變
		for (i = 0; i < N; i++)
		{
			a.push_back(i + 1);
		}
		cout << "a.capacity()=" << a.capacity() << endl;	/* a.capacity()=28,可知pushback()會預留部分空間*/
		cout << "a.size()=" << a.size() << endl << endl;	/* a.size()=20,實際空間等於元素個數*/

		//②給 a 重設長度:研究 resize() 對記憶體的改變
		a.resize(30);
		cout << "a.capacity()=" << a.capacity() << endl;	/* a.capacity()=42,可知resize()會對快取區進行重新分配和空間預留*/
		cout << "a.size()=" << a.size() << endl << endl;	/* a.capacity()=30,可知resize()會產生初始值*/
															
		//③給 c 重設長度:研究 resize() 對記憶體的改變
		c.resize(25);
		cout << "c.capacity()=" << c.capacity() << endl;	/* c.capacity()=25,可以發現:當對空容器resize(),不會預留空間*/
		cout << "c.size()=" << c.size() << endl << endl;	/* c.capacity()=25*/

		//④給 a 預設長度:研究 reserve() 對記憶體的改變
		a.reserve(50);
		cout << "a.capacity()=" << a.capacity() << endl;	/* a.capacity()=50,可知reserve()不會對快取區進行重新分配和空間預留*/
		cout << "a.size()=" << a.size() << endl << endl;	/* a.size()=30,可知reserve()不會產生初始值*/
		
		//⑤給 a 新增超出它預設capcity的元素:研究 capcity 的變化
		for (i = 0; i < 25; i++)
		{
			a.push_back(i + 1);
		}
		cout << "a.capacity()=" << a.capacity() << endl;	/* a.capacity()=75,可知當元素超出預設的capcity,就會觸發空間預留*/
		cout << "a.size()=" << a.size() << endl << endl;	/* a.size()=55*/
		
		/*二維記憶體*/
		cout << "e.capacity()=" << e.capacity() << endl;		/* e.capacity()=0,列的capcity報錯 */
		
		cout << "f.capacity()=" << f.capacity() << endl;		/* f.capacity()=20 */
		cout << "f[0].capacity()=" << f[0].capacity() << endl;	/* f[0].capacity()=0,指定行則有列的capcity */

		cout << "g.capacity()=" << g.capacity() << endl;		/* g.capacity()=20 */
		cout << "g[2].capacity()=" << g[2].capacity() << endl;	/* g[2].capacity()=3,可知每行都被插入了相同的元素 */

		/*經過一維vector的探究,選出一些適合二維的節省資源的定義方式!*/

		//①對於可求得固定行、列資訊的二維vector,定義如下:
		vector<vector<int>>h{ N };
		for (i = 0; i < h.size(); i++)
		{
			h[i].reserve(T);
		}
		cout << "h.capacity()=" << h.capacity() << endl;		/* h.capacity()=20 */
		cout << "h[0].capacity()=" << h[0].capacity() << endl;	/* h[0].capacity()=10 */
		cout << endl;

		//②對於可求得固定行資訊,但是列長未知的二維vector,定義如下:
		vector<vector<int>>p{ N };
		/*通過push_back壓入元素,會有預留空間*/
		for (i = 0; i < p.size(); i++)
		{
			for (j = 0; j < i + 1; j++)
			{
				p[i].push_back(j + 1);
			}
		}
		/*看看預留空間:發現確實有預留現象!*/
		for (i = 0; i < p.size(); i++)
		{
			cout << "p[" << i << "].size()=" << p[i].size() << endl;
			cout << "p[" << i << "].capacity()=" << p[i].capacity() << endl;
		}
		cout << endl;
		/*有沒有辦法切去多餘的空間?——利用swap()方法去除vector多餘的容量*/
		vector<vector<int>>(p).swap(p);
		for (i = 0; i < p.size(); i++)
		{
			cout << "p[" << i << "].size()=" << p[i].size() << endl;
			cout << "p[" << i << "].capacity()=" << p[i].capacity() << endl;
		}
		cout << endl;

		//③對於無任何資訊的二維vector,直接定義空的就行。
		vector<vector<int>>t;
		/*注意:若一開始沒有定義行,那麼是無法通過reserve()固定行的;
			只能通過resize()的方式。
		*/
	}
};
/*類Vector_release:探究如何徹底釋放在類中定義的vector的記憶體*/
class Vector_release
{
private:
	int i, j;
	
public:
	vector<vector<int>> a;
	vector<vector<int>> b{ N };
	vector<vector<int>> c;
	vector<int>d{ 1,2,3 };
	
	void define()
	{
		//①經過以上測試的探索,我們可以有新的定義方式:用 行、列resize()+swap()
		a.resize(N);
		for (i = 0; i < a.size(); i++)
		{
			a[i].resize(i + 1);
		}
		vector<vector<int>>(a).swap(a);			/*切除多餘空間*/
		//輸出
		for (i = 0; i < a.size(); i++)
		{
			for (j = 0; j < a[i].size(); j++)
			{
				cout << a[i][j] << " ";
			}
			cout << endl;
		}
		cout << endl;
		/*cout << "a.size()" << a.size() << endl;
		for (i = 0; i < a.size(); i++)
		{
			cout << "a[" << i << "].capacity()=" << a[i].capacity() << endl;
		}
		cout << endl;*/

		//②用 指定行、列reserve()+push_back()定義
		for (i = 0; i < N; i++)
		{
			b[i].reserve(T);
		}
		for (i = 0; i < N; i++)
		{
			for (j = 0; j < T; j++)
			{
				b[i].push_back(1);
			}
		}
		cout << "bbbbb" << endl;
		for (i = 0; i < b.size(); i++)
		{
			for (j = 0; j < b[i].size(); j++)
			{
				cout << b[i][j] << "  ";
			}
			cout << endl;
		}
		cout << endl;

		//③copy一個
		c = a;


		

	}

	void clean()
	{
		

		//b.clear();	/*報錯!:因為b在定義時,指定了行數,所以不能clear行*/
		
		//for (i = 0; i < b.size(); i++)
		//{
		//	b[i].clear();	
		//}/*可以清空列元素,但是列的capacity還在。但至少可以保證迴圈時的push_back()不會溢位記憶體*/
		
		for (i = 0; i < b.size(); i++)
		{
			vector<int>().swap(b[i]);
		}/*可以清空列元素以及列的capacity。*/

		//c.clear();/*二維vector.clear(),可以徹底清除列的capacity,但是保留著行的capacity*/

		vector<vector<int>>().swap(c);/*利用swap()徹底清除capacity*/
		
		d.clear();/*一維vector.clear(),保留著列的capacity*/
		
	}

};
int main()
{
	Vector_define v1;
	v1.test1();

	Vector_memory v2;
	v2.test2();

	Vector_release v3;
	for (int it = 0; it < 4; it++)
	{
		cout << "第" << it << "次:" << endl;
		
		v3.define();
		v3.clean();
		
		for (int i = 0; i < v3.a.size(); i++)
		{
			cout << "a[i].capacity[" << i << "]=" << v3.a[i].capacity() << "  ";
		}
		cout << endl << endl;
		
		for (int i = 0; i < v3.b.size(); i++)
		{
			cout << "b[i].capacity[" << i << "]=" << v3.b[i].capacity() << "  ";
		}
		cout << endl << endl;
		
		cout << "c.capacity()=" << v3.c.capacity() << endl;
		for (int i = 0; i < v3.c.size(); i++)
		{
			cout << "c[i].capacity[" << i << "]=" << v3.c[i].capacity() << "  ";
		}
		cout << endl;
		cout << "d.capacity()=" << v3.d.capacity() << endl;
	}
	
	
	



	return 0;
	system("pause");
}

參考文章:

1.reserve和resize_lusic01的專欄-CSDN部落格

2.C++ vector中的resize,reserve,size和capacity函式講解

3.C++ vector swap()去除多餘容量

4.vector記憶體機制和效能分析_https://github.com/JelinYao-CSDN部落格_vector 記憶體

5.vector 的記憶體分配問題_藏經閣-CSDN部落格

6.STL中vector的記憶體分配與正確釋放_System Architect-CSDN部落格_vector指標記憶體釋放

7.c++ vector 初始化_C++語言之vector記憶體分配技術

8.vector的記憶體分配方式_zhuzhubility的部落格-CSDN部落格

https://zhuanlan.zhihu.com/p/338390842