1. 程式人生 > >【原創】C++ 動態陣列 vector 詳解

【原創】C++ 動態陣列 vector 詳解

一、引入

引入:略

vector收錄在STL裡,是一種特殊的資料結構。它的中文名字叫做“動態陣列”或者“不定長陣列”,有時也被翻譯成“容器”

說白了,vector就是一個功能強大的陣列。下面讓我們來體驗它強大的功能吧!

二、vector的標頭檔案

vector收錄在std庫裡,所以呼叫vector需要

#include<vector>

using namespace std;

這兩個標頭檔案。

三、vector的宣告與建構函式

既然是“動態陣列”,vector是一個什麼陣列呢,int?double?或者結構體陣列?

我們可以這樣宣告一個vector:

vector <資料型別> 動態陣列名;

比如:

vector <int> i;//一個int的動態陣列

vector <char> c;//一個char的動態陣列

vector <node> n;//一個node的動態陣列(node是結構體名)

如果你想賦初值,你可以:

vector <int> M(a,b);//在M裡裝a個b

vector <int> N(a); //在N裡裝a個0

當然你也可以:

vector <int> A;

vector <int> B(A);//一個和A一模一樣的動態陣列

vector <int> C(B.begin()+l,B.end()-r);//繼承B動態陣列下標[l,B.end()-r)

的值,注意,下標從0開始,begin(),end(),size()三個函式見下文

四、vector的解構函式

很簡單,你可以vector <A> B;//A是某種資料結構,B是動態陣列名

如果你想析構它,只需呼叫B.~vector<A>(); 即可。

也就是說,vector的解構函式是:動態陣列名.~vector<該陣列的資料結構>();

五、vector的基本操作

以vector <int> v為例:

① v[i]或v.at(i)//返回v[i]的

② v.size();//返回v陣列元素總個數

③ v.front();//返回v陣列第一個元素的

④ v.back();//返回v陣列最後一個

元素的

⑤ v.clear();//清空v陣列

⑥ v.begin();//返回v陣列第一個數的下標

⑦ v.end();//返回v陣列最後一個數的下標

⑧ v.empty();//判斷v陣列是否為空,是空則返回1(true)非空(有元素)則返回0(false)

⑨ v.swap(v1);//v1是另一個動態陣列,將v和v1元素互換

⑩ swap(v,v1);//同⑨

注意:再次重申,vector的下標是從0開始的!

注意:除v[i]外,其餘都是vector的自帶函式,因此必須添上括號

五、vector的插入

std庫提供了好幾種插入,這裡講最為常用的三種。

① v.push_back(a);//在v陣列的尾部插入數a

比如:

有一個動態陣列x:2017 2333

呼叫x.push_back(666);

則x:2017 2333 666

② v.insert(v.begin()+k,a);//在下標k的前面插入數a,k之後的數依次後退一位

//記住,下標是從0開始的!

比如:

動態陣列x:1 2 3 4 5 6 

呼叫x.insert(x.begin()+2,100);

則x:1 2 100 3 4 5 6 

③ x.insert(x.begin()+k,p,a);//在下標k前插入p個a

六、vector的刪除

也有三種,

① v.pop_back()//刪除最後一個元素

② v.erase(v.begin()+k);//刪除下標為k的數,返回下一個位置的下標

③ v.erase(v.begin()+l,v.end()-r);//刪除下標[l,v.end()-r)的元素

七、vector的記憶體機制

vector能裝多少個元素呢?它的長度是多長呢?接下來就要簡單地介紹一下vector的記憶體機制。

先介紹幾個函式吧:

v.capacity();//返回v陣列的長度,就相當於int v[20000];的20000

v.resize(k);//將v陣列的長度設為k

現在讓我們來研究一下vector的記憶體機制。

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const unsigned int maxn=2147483647;
vector <unsigned int> v;
int main()
{
	//printf("%d\n",v.capacity());
	//v.resize(1000);
	unsigned int last=v.capacity();
	printf("%d\n",last);
	for(unsigned int i=1;i<=maxn;i++)
	{
		v.push_back(i);
		unsigned int a=v.capacity();
		if(a!=last)
		{
			printf("%d\n",a);
			last=a;
		}
	}
}


這個驗證程式測試了vector的長度上限,現在讓我們來看看輸出結果:

0
1
2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
131072
262144
524288
1048576
2097152
4194304
8388608
16777216
33554432
67108864
134217728


This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

最後程式輸出了這一行英文,然後就會崩潰。這句話的大概意思是:程式執行時申請以某種非正常的方式結束它,請聯絡開發團隊以取得更多資訊。

(也就是說,我們把vector玩爆了。)

我們來看看它的規律,我們可以發現,每一次,它的記憶體都翻了一倍!!

我們再來看看它什麼時候翻倍。

在printf("%d\n",a);時,再輸出此時的v.size();

此時的程式:

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const unsigned int maxn=2147483647;
vector <unsigned int> v;
int main()
{
	//printf("%d\n",v.capacity());
	//v.resize(1000);
	unsigned int last=v.capacity();
	printf("%d\n",last);
	for(unsigned int i=1;i<=maxn;i++)
	{
		v.push_back(i);
		unsigned int a=v.capacity();
		if(a!=last)
		{
			printf("size()=%d -> capacity()=%d\n",v.size(),a);
			last=a;
		}
	}
}


此時的輸出結果:

0
size()=1 -> capacity()=1
size()=2 -> capacity()=2
size()=3 -> capacity()=4
size()=5 -> capacity()=8
size()=9 -> capacity()=16
size()=17 -> capacity()=32
size()=33 -> capacity()=64
size()=65 -> capacity()=128
size()=129 -> capacity()=256
size()=257 -> capacity()=512
size()=513 -> capacity()=1024
size()=1025 -> capacity()=2048
size()=2049 -> capacity()=4096
size()=4097 -> capacity()=8192
size()=8193 -> capacity()=16384
size()=16385 -> capacity()=32768
size()=32769 -> capacity()=65536
size()=65537 -> capacity()=131072
size()=131073 -> capacity()=262144
size()=262145 -> capacity()=524288
size()=524289 -> capacity()=1048576
size()=1048577 -> capacity()=2097152
size()=2097153 -> capacity()=4194304
size()=4194305 -> capacity()=8388608
size()=8388609 -> capacity()=16777216
size()=16777217 -> capacity()=33554432
size()=33554433 -> capacity()=67108864
size()=67108865 -> capacity()=134217728


This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

(結尾還是那句英文。。。。)

我們可以看到:

設當前v.capacity()=c,v.size()=s;如果s=c+1,那麼c就會加倍。

這是一個初始長度為0的動態陣列,接著我們來看看初始長度不為0的情況。

此時程式碼:

#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
const unsigned int maxn=2147483647;
const unsigned int beg=1250;//這是可修改的
vector <unsigned int> v;
int main()
{
	v.resize(beg);
	unsigned int last=v.capacity();
	printf("At first , capacity() = %d\n",last);
	for(unsigned int i=1;i<=maxn;i++)
	{
		v.push_back(1);
		unsigned int a=v.capacity();
		if(a!=last)
		{
			printf("size()=%d -> capacity()=%d\n",v.size(),a);
			last=a;
		}
	}
}


結果(只保留了一部分):

At first , capacity() = 1000
size()=1001 -> capacity()=2000
size()=2001 -> capacity()=4000
size()=4001 -> capacity()=8000
size()=8001 -> capacity()=16000

At first , capacity() = 5000
size()=5001 -> capacity()=10000
size()=10001 -> capacity()=20000
size()=20001 -> capacity()=40000
size()=40001 -> capacity()=80000
size()=80001 -> capacity()=160000

At first , capacity() = 2333
size()=2334 -> capacity()=4666
size()=4667 -> capacity()=9332
size()=9333 -> capacity()=18664
size()=18665 -> capacity()=37328
size()=37329 -> capacity()=74656
size()=74657 -> capacity()=149312
size()=149313 -> capacity()=298624
size()=298625 -> capacity()=597248

多次試驗後,我們可以得出結論:

當動態陣列內的元素比動態陣列長度多一時,動態陣列長度翻倍!

也就是說:if(v.size()-1==v.capacity()) v.resize(v.capacity()*2);

而長度翻倍是很花時間的。所以說做題的時候,記得事先把vector的長度拉得足夠長,以免執行的時候,vector長度翻倍浪費時間。

最後一個問題,vector最多能裝多少個元素呢?

我們可以用函式:

v.max_size();

來得到。

下列是一個常用的資料結構對應的max_size();

bool -> 4294967295

char -> 4294967295

int-> 1073741823

unsigned int -> 1073741823

float -> 1073741823

double-> 536870911

long long -> 536870911

unsigned long long ->536870911