vector 是同一種類型的對象的集合,每個對象都有一個對應的整數索引值。把 vector稱為容器,是因為它可以包含其他對象。
使用 vector 之前,必須包含相應的頭文件:
#include <vector>
using std::vector;
vector 是一個類模板(class template)。因此,可以定義保存 string 對象的 vector,或保存 int 值的 vector,又或是保存自定義的類類型對象vector。
聲明從類模板產生的某種類型的對象,需要提供附加信息,信息的種類取決於模板。以 vector 為例,必須說明 vector 保存何種對象的類型,通過將類型放在類型放在類模板名稱后面的尖括號中來指定類型:
vector<int> ivec; // ivec holds objects of type int
vector<Sales_item> Sales_vec; // holds Sales_items
vector 不是一種數據類型,而只是一個類模板,可用來定義任意多種數據類型。vector 類型的每一種都指定了其保存元素的類型。因此,vector<int> 和 vector<string> 都是數據類型。
vector 對象的定義和初始化
vector<T> v1; |
vector 保存類型為 T 對象。默認構造函數 v1 為空。 |
vector<T> v2(v1); |
v2 是 v1 的一個副本。 |
vector<T> v2=v1; |
與vector<T> v2(v1)等價 |
vector<T> v3(n, i); |
v3 包含 n 個值為 i 的元素。 |
vector<T> v4(n); |
v4 含有值初始化的元素的 n 個副本。 |
vector<T> v5{a,b,c…}; |
v5包含了初值個數的元素,每個元素被賦予相應的初始值。 |
vector<T> v5={a,b,c…}; |
等價於vector<T> v5{a,b,c…}; |
若要創建非空的 vector 對象, 必須給出初始化元素的值。當把一個 vector對象復制到另一個 vector 對象時, 新復制的 vector 中每一個元素都初始化為原 vectors 中相應元素的副本。但這兩個 vector 對象必須保存同一種元素類型。
列表初始化vector對象
列表初始化是C++11中新定義的一種為vector對象的元素賦值,此時,用花括號括起來的0個或多個初始元素值被賦給vector對象:
vector<string> articles={“a”,“an”,“the”};
初始化的幾點注意:
使用拷貝初始化時,只能提供一個初始值;
如果提供的是一個類內初始值,則只能使用拷貝初始化或使用花括號初始化;
如果提供的是初始元素值的列表,則只能把初始值都放在花括號里進行列表初始化,而不能放在圓括號中:
vector<string> articles={“a”,“an”,“the”}; //列表初始化
vector<string> articles=(“a”,“an”,“the”); //錯誤
創建確定個數的元素
可以用元素個數和元素值對 vector 對象進行初始化。構造函數用元素個數來決定 vector 對象保存元素的個數,元素值指定每個元素的初始值:
vector<int> ivec4(10, -1); // 10 elements, each initialized to -1
vector<string> svec(10, "hi!"); // 10 strings, each initialized to "hi!"
值初始化
如果沒有指定元素的初始化式,那么標准庫將自行提供一個元素初始值進行值初始化(value initializationd)。這個由庫生成的初始值將用來初始化容器中的每個元素,具體值為何,取決於存儲在 vector 中元素的數據類型。
如果 vector 保存內置類型(如 int 類型)的元素,那么標准庫將用 0 值創建元素初始化式:
vector<int> fvec(10); // 10 elements, each initialized to 0
如果 vector 保存的是含有構造函數的類類型(如 string)的元素,標准庫將用該類型的默認構造函數創建元素初始化式:
vector<string> svec(10); // 10 elements, each an empty string
如果只提供了元素的數量而沒有設定初始值,只能使用直接初始化:
vector<int> vi=10; //錯誤,必須使用直接初始化的形式指定向量大小
初始化值還是元素數量
用一個整數來初始化vector<int>時,整數的含義可能是vector對象的容量也可以是元素的值,可以使用花括號或圓括號來區分相應的定義:
vector<int> v1(10); //v1有10個元素,每個元素的值都是0
vector<int> v2{10}; //v2有1個元素,該元素的值是10
vector<int> v3(10,1); //v3有10個元素,每個元素的值都是1
vector<int> v4{10,1}; //v4有2個元素,分別是10和1
如果使用的是圓括號,可以說提供的值是用來構造vector對象的。
如果使用的是花括號,即為列表初始化該vector對象,也就是說,初始化過程盡可能地把花括號內的值當成是元素初始值的列表來處理,只有在無法執行列表初始化時才會考慮其他初始化方式。
如果初始化時用了花括號的形式但是提供的值又不能用來列表初始化,就要考慮用這樣的值來構造vector對象:
vector<string> v5{“hi”}; vector<string> v6 (“hi”); //錯誤,不能使用字符串字面值構建vector對象
vector<string> v7{10}; //v7有10個默認初始化的元素
vector<string> v8{10,“hi”}; //v8有10個值為“hi”的元素
上面只有v5是列表初始化,要想列表初始化vector對象,花括號里的值必須與元素類型相同。v7和v8提供的值不能作為元素的初始值,因此編譯器會嘗試使用默認初始化方式來初始化vector對象。
向vector對象中添加元素
vector對象的初始化方式有三種:
初始值已知且很少;
初始化值是另一個對象的副本,元素值都一樣;
更一般的情況是:創建一個vector對象時並不清楚實際所需要的元素個數,元素的值也無法確定,或者元素的初始值已知,但是這些值的數量較大且各不相同,那么創建vector對象的時候執行初始化操作顯得過於繁瑣。
push_back 操作接受一個元素值,並將它作為一個新的元素添加到 vector對象的后面,也就是“插入(push)”到 vector 對象的“后面(back)”:
// read words from the standard input and store them as elements in a vector
string word; vector<string> text; // empty vector
while (cin >> word) { text.push_back(word); // append word to text
}
雖然可以對給定元素個數的 vector 對象預先分配內存,但更有效的方法是先初始化一個空 vector 對象,然后再動態地增加元素。
其它對vector 對象的操作
v.empty() |
如果 v 為空,則返回 true,否則返回 false。 |
v.size() |
返回 v 中元素的個數 |
v.empty() |
如果 v 為空,則返回 true,否則返回 false。 |
v.push_back(t) |
在 v 的末尾增加一個值為 t 的元素。 |
v[n] |
返回 v 中位置為 n 的元素。 |
v1 = v2 |
把 v1 的元素替換為 v2 中元素的副本。 |
v1 == v2 |
如果 v1 與 v2 相等,則返回 true。 |
!=, <, <=,>, and >= |
保持這些操作符慣有的含義。 |
vector 對象的 size
成員函數size 返回相應 vector 類定義的 size_type 的值。使用 size_type 類型時,必須指出該類型是在哪里定義的。vector 類型總是包括總是包括 vector 的元素類型:
vector<int>::size_type // ok
vector::size_type // error
vector 的下標操作
vector 中的對象是沒有命名的,可以按 vector 中對象的位置來訪問它們。通常使用下標操作符來獲取元素。
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;
下標操作不添加元素
不能使用vector 的下標操作添加元素,下標只能用於獲取已存在的元素。
vector<int> ivec; // empty vector
for (vector<int>::size_type ix = 0; ix != 10; ++ix)
ivec[ix] = ix; //錯誤,不能使用下標操作添加元素
這個循環的正確寫法應該是:
for (vector<int>::size_type ix = 0; ix != 10; ++ix) ivec.push_back(ix); // ok: adds new element with value ix