1.標準庫vector類型
vector是同一種類型的對象的集合,每個對象都對應一個相應的索引值,同string對象一樣,標準庫將負責管理與存儲元素有關的內存。
vector稱之爲容器。
使用vector前,包含相應的頭文件
#include <vector>
using std::vector;
vector是一個類模板,因此可以定義string對象的vector,int對象的vector,或者是自定義類類型的vector。
vector<int> ivec;
vector<Sale_type> svec;
注意:vector不是一種數據類型,只是一種類模板,vector<int>是一種數據類型。
vector對象的定義和初始化
1.創建確定個數的元素
vector<int> ivec1;
vector<int> ivec2(ivec1);
vector<string> svec(ivec);
vector<int> ivec4(10,-1);
vector<string> svec2(10,”hi!”)
注意:vector對象的重要屬性是可以在運行時動態的添加元素。因爲vector增長的效率高,在元素已知的情況下,最好是動態的添加元素,而不是預先分配好合適的存儲空間。
2.值初始化
如果沒有指定元素的初始化式,那麼標準庫將自行提供一個元素初始值進行值初始化,初始化vector中的每一個對象。初始化的結果,取決於vector中每個對象的數據類型。
vector<int> fvec(10);//10elements,each initialized to 0
如果vector保存的對象爲內置類型,那麼標準庫將用0初始化。Char類型初始化爲空字符
vector<string> svec(10);
如果vector保存的是含有構造函數的類類型的對象,標準庫將用該類類型的默認構造函數進行初始化。
還有一種情況,vector保存的是沒有定義任何構造函數的類類型,這時,標準庫仍產生一個帶初始值的對象。
如果vector保存的是一些有自定義構造函數但沒有默認構造函數的類的對象時,不能只提供創建的對象的元素的個數,還要提供元素的初始化值。
vector對象的操作
1.vector對象的size
empty 和size操作類似於string類型的相關操作,size成員函數返回vector定義的size_type類型的值。
vector<int>::size_type; //ok
vector ::size_type; //error
int main()
{
vector<int> ivec(10);
cout << ivec.size()<<endl;
if (ivec.empty())
{
cout << "empty" << endl;
}
else
{
cout << "not empty" << endl;
}
getchar();
return 0;
}
2.向vector中添加元素
上面提過,在vector使用時,如果vector定義的對象的數目已經確定,也儘量不要直接分配好適當的存儲空間,而是在運行時動態的分配空間,當然此時就要用到push_back成員函數。Push(元素)到vector的back
3.vector的下標操作
類似於string對象的下標操作
下標的類型爲vector定義的size_type類型
遍歷輸出:
int main()
{
vector<string> svec;
string s;
while (cin >> s)
{
svec.push_back(s);
}
for (vector<string>::size_type index = 0; index != svec.size(); ++index)
{
cout << svec[index] << " ";
}
cout << endl;
system("pause");
return 0;
}
Vector下標操作的對象作爲左值賦值:
int main()
{
vector<string> svec;
string s;
while (cin >> s)
{
svec.push_back(s);
}
for (vector<string>::size_type index = 0; index != svec.size(); ++index)
{
cout << svec[index] << " ";
}
cout << endl;
for (vector<string>::size_type index = 0; index != svec.size(); ++index)
{
svec[index] = "hello";
}
for (vector<string>::size_type index = 0; index != svec.size(); ++index)
{
cout << svec[index] << " ";
}
cout << endl;
system("pause");
return 0;
}
關鍵概念:良好的c++編程風格
1.c++程序員習慣於優先選用!=而不是<來編寫循環判斷條件。
2.上述程序,並沒有在循環判斷條件前保存size()的返回值,而是在循環條件中調用size()函數,這是因爲vector是可以動態變化的數據結構,在程序運行過程中size()的返回值可能會發生變化,如果判斷條件用的是以前size()返回值,那麼就會產生錯誤。所以更傾向於在每次循環中測試size的當前值,而不是存儲size返回值的副本。
4.下標操作不添加元素
必須是已存在的元素才能用下標操作符進行索引
int main()
{
vector<int> ivec;
ivec[0] = 10;//error
ivec.push_back(10);//ok
}
2.迭代器簡介
除了使用下標訪問vector容器中的對象,標準庫還提供了另一種訪問元素的辦法:使用迭代器。迭代器是一種檢查容器內元素並遍歷元素的數據類型。
標準庫爲每一種標準容器都定義了一種迭代器,因此對於容器內元素的訪問,迭代器要比下標操作更爲普遍,因爲並不是每種標準容器都支持下標訪問,而每種標準容器都支持迭代器訪問。
注意c++除了標準容器還有非標準容器
1.容器的iterator類型
標準庫爲每種標準容器都定義了一種迭代器類型:
vector<string>::iterator iter;
2.begin和end操作
begin返回的迭代器指向容器中的第一個元素,end返回的迭代器指向末端元素的下一個,它指向了一個容器中不存在的元素。若容器爲空,則begin和end返回的迭代器相同。
3.vector迭代器的自增和解引用運算
迭代器自增來指向容器中下一個位置的對象,解引用運算來訪問迭代器指向的對象的內容
由於end操作返回的迭代器不指向任何元素,因此不能對end返回的迭代器進行解引用或自增操作。
4.迭代器的比較操作
== != 用來判斷迭代器是否指向同一個位置的元素
5.實例
int main()
{
vector<int> ivec(10,1);
for (vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); ++iter)
{
cout << *iter << " ";//解引用運算符
}
cout << endl;
for (vector<int>::iterator iter = ivec.begin(); iter!= ivec.end(); ++iter)
{
*iter = 0;
cout << *iter << " ";
}
cout << endl;
system("pause");
return 0;
}
6.Const_iterator
Const_iterator指的是解引用後得到的是一個const引用的對象,也就是說不能修改其值,但const_iterator是可以變化的:迭代器指向的位置可以發生變化,但迭代器指向的位置的值不能夠發生變化
Const的vector容器的iterator,這時的iterator是一個const類型,也就是說iterator指向的位置不能夠發生變化,但其指向的位置的值是可以發生變化的,並且iterator在定義是就需要初始化,並且初始化後不能夠再變化。
int main()
{
vector<int> ivec(10,1);
for (vector<int>::const_iterator iter = ivec.begin(); iter != ivec.end(); ++iter)
{
*iter = 0;//error
}
for (const vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); ++iter)//++iter error
{
*iter = 0;
}
return 0;
}
迭代器的算術操作:
Iterator+n
Iterator-n
返回從當前iterator指向的位置向前或向後移動n個位置的iterator,加或減之後指向的元素必須在vector容器中,或在末端的下一個元素。
Iter1-iter2
用來計算兩個迭代器之間的距離,其結果爲difference_type類型,signed,類似於size_type。
int main()
{
vector<int> ivec(10);
vector<int>::difference_type dis;
vector<int>::iterator iter1, iter2;
iter1 = ivec.begin();
iter2 = ivec.end();
dis = iter2 - iter1;
cout << dis << endl;
dis = iter1 - iter2;
cout << dis << endl;
getchar();
return 0;
}
可以用迭代器算術操作來移動迭代器指向容器中的某個元素:
Iter=vec.begin()+vec.size()/2;
迭代器指向容器中中間位置的元素(容器中有奇數個,指向中間位置;偶數個,指向中間位置的後一個)
注意:在進行push_back操作後就不能在信賴iterator指向的值了。