一、vector的基本概念
vector是同一種類型的對象的集合,每個對象都有一個對應的整數索引值。和string對象一樣,標準庫負責管理存儲元素的相關內存。我們把vector稱爲容器,是因爲它可以包含其他對象。一個容器中的所有對象都必須是同一種類型的。使用vector之前,必須包含相應的頭文件。
#include<vector>
usingstd::vector;
vector是一個類模板(classtemplate),這個類和函數定義可用於不同的數據類型上。因此,我們可以定義保存string對象的vector,或保存int值的vector,又或是保存自定義的類類型對象(如Sales_item對象)的vector。聲明從類模板產生的某種類型的對象,需要提供附加信息,信息的種類取決於模板。以vector爲例,必須說明vector保存何種對象的類型,通過將類型放在類模板名稱後面的尖括號中來指定類型:
vector<int>ivec;//ivecholdsobjectsoftypeint
vector<Sales_item>Sales_vec;//holdsSales_items
和其他變量定義一樣,定義vector對象要指定類型和一個變量的列表。上面的第一個定義,類型是vector<int>,該類型即是含有若干int類型對象的vector,變量名爲ivec。第二個定義的變量名是Sales_vec,它所保存的元素是Sales_item類型的對象。
vector不是一種數據類型,而只是一個類模板,可用來定義任意多種數據類型。vector類型的每一種都指定了其保存元素的類型。因此,vector<int>和vector<string>都是數據類型。
二、vector的基本操作
1)vector對象的定義和初始化
vector類定義了好幾種構造函數,用來定義和初始化vector對象。如下示出幾種初始化vector對象的方式:
vector<T>v1; |
vector保存類型爲T的對象。默認構造函數v1爲空。 |
vector<T>v2(v1); |
v2是v1的一個副本。 |
vector<T>v3(n,i); |
v3包含n個值爲i的元素。 |
vector<T>v4(n); |
v4含有值初始化的元素的n個副本。 |
a、創建確定個數的元素
若要創建非空的vector對象,必須給出初始化元素的值。當把一個vector對象複製到另一個vector對象時,新複製的vector中每一個元素都初始化爲原vector中相應元素的副本。但這兩個vector對象必須保存同一種元素類型:
vector<int>ivec1;//ivec1holdsobjectsoftypeint
vector<int>ivec2(ivec1);//ok:copyelementsofivec1intoivec2
vector<string>svec(ivec1);//error:svecholdsstrings,notints
可以用元素個數和元素值對vector對象進行初始化。構造函數用元素個數來決定vector對象保存元素的個數,元素值指定每個元素的初始值:
vector<int>ivec4(10,-1);//10elements,eachinitializedto-1
vector<string>svec(10,"hi!");//10strings,eachinitializedto"hi!"
關鍵概念:vector對象動態增長
vector對象(以及其他標準庫容器對象)的重要屬性就在於可以在運行時高效地添加元素。因爲vector增長的效率高,在元素值已知的情況下,最好是動態地添加元素。
雖然可以對給定元素個數的vector對象預先分配內存,但更有效的方法是先初始化一個空vector對象,然後再動態地增加元素。
b、值初始化
如果沒有給出元素的初始化式,那麼標準庫將提供一個值初始化的(valueinitialized)元素初始化式。這個由庫生成的初始值用於初始化容器中的每個元素。而元素初始化式的值取決於存儲在vector中元素的數據類型。
如果vector保存內置類型(如int類型)的元素,那麼標準庫將用0值創建元素初始化值:
vector<string>fvec(10);//10elements,eachinitializedto0
如果向量保存類類型(如string)的元素,標準庫將用該類型的默認構造函數創建元素初始值:
vector<string>svec(10);//10elements,eachanemptystring
c、vector的操作
empty() |
如果 v 爲空,則返回 true, 否則返回 false 。 |
v . size () |
返回 v 中元素的個數。 |
v . push _ back ( t ) |
在 v 的末尾增加一個值爲 t 的元素。 |
v [ n ] |
返回 v 中位置爲 n 的元素。 |
v1 = v2 |
把 v1 的元素替換爲 v2 中元素的副本。 |
v1 == v2 |
如果 v1 與 v2 相等,則返回 true 。 |
!=, <, <=, >, >= |
保持這些操作符慣有的含義。 |
(1)vector對象的size
empty和size操作類似於string類型的相關操作。成員函數size返回相應vector類定義的size_type的值。
使用size_type類型時,必須指出該類型是在哪裏定義的。vector類型總是包括vector的元素類型:
vector<int>::size_type//ok
vector::size_type//error
(2)向vector添加元素
push_back()操作接受一個元素值,並將它作爲一個新的元素添加到vector對象的後面,也就是“插入(push)”到vector對象的“後面(back)”:
//read words from the standard input and store the elements in a vector
stringword;
vector<string>text;//emptyvector
while(cin>>word){
text.push_back(word);//appendwordtotext
}
該循環從標準輸入讀取一系列string對象,逐一追加到vector對象的後面。首先定義一個空的vector對象text。每循環一次就添加一個新元素到vector對象,並將從輸入讀取的word值賦予該元素。當循環結束時,text就包含了所有讀入的元素。
(3)vector的下標操作
vector中的對象是沒有命名的,可以按vector中對象的位置來訪問它們。通常使用下標操作符來獲取元素。vector的下標操作類似於string類型的下標操作。
vector的下標操作符接受一個值,並返回vector中該對應位置的元素。vector元素的位置從0開始。下例使用for循環把vector中的每個元素值都重置爲0:
//reset the elements in the vector to zero
for(vector<int>::size_type ix=0;ix!=ivec.size();++ix)
ivec[ix]=0;
和string類型的下標操作符一樣,vector下標操作的結果爲左值,因此可以像循環體中所做的那樣實現寫入。另外,和string對象的下標操作類似,這裏用size_type類型作爲vector下標的類型。
在上例中,即使ivec爲空,for循環也會正確執行。ivec爲空則調用size返回0,並且for中的測試比較ix和0。第一次循環時,由於ix本身就是0,則條件測試失敗,for循環體一次也不執行。
關鍵概念:安全的泛型編程
C++程序員習慣於優先選用!=而不是<來編寫循環判斷條件。
(4)下標操作不添加元素
初學C++的程序員可能會認爲vector的下標操作可以添加元素,其實不然:
vector<int>ivec;//emptyvector
for(vector<int>::size_typeix=0;ix!=10;++ix)
ivec[ix]=ix;//disaster:ivec has no elements
上述程序試圖在ivec中插入10個新元素,元素值依次爲0到9的整數。但是,這裏ivec是空的vector對象,而且下標只能用於獲取已存在的元素。
這個循環的正確寫法應該是:
for(vector<int>::size_typeix=0;ix!=10;++ix)
ivec.push_back(ix);//ok:adds new element with value ix
必須是已存在的元素才能用下標操作符進行索引。通過下標操作進行賦值時,不會添加任何元素。
警告:僅能對確知已存在的元素進行下標操作
對於下標操作符([]操作符)的使用有一點非常重要,就是僅能提取確實已存在的元素,例如:
vector<int>ivec;//empty vector
cout<<ivec[0];//Error: ivec has no elements!
vector<int>ivec2(10);//vector with 10 elements
cout<<ivec[10];//Error:ivec has elements 0...9
試圖獲取不存在的元素必然產生運行時錯誤。
附:常用方法
1.push_back() 在數組的最後添加一個數據
2.pop_back() 去掉數組的最後一個數據
3.at() 得到編號位置的數據
4.begin() 得到數組頭的指針
5.end() 得到數組的最後一個單元+1的指針
6.front() 得到數組頭的引用
7.back() 得到數組的最後一個單元的引用
8.max_size() 得到vector最大可以是多大
9.capacity() 當前vector分配的大小
10.size() 當前使用數據的大小
11.resize() 改變當前使用數據的大小,如果它比當前使用的大,者填充默認值
12.reserve() 改變當前vecotr所分配空間的大小
13.erase() 刪除指針指向的數據項
14.clear() 清空當前的vector
15.rbegin() 將vector反轉後的開始指針返回(其實就是原來的end-1)
16.rend() 將vector反轉構的結束指針返回(其實就是原來的begin-1)
17.empty() 判斷vector是否爲空
18.swap() 與另一個vector交換數據