《c++ primer》——2 標準庫vector類型和迭代器iterator

1.標準庫vector類型

vector是同一種類型的對象的集合,每個對象都對應一個相應的索引值,同string對象一樣,標準庫將負責管理與存儲元素有關的內存

vector稱之爲容器。

使用vector前,包含相應的頭文件

#include <vector>
using std::vector;

vector是一個類模板,因此可以定義string對象的vectorint對象的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(元素)vectorback

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.beginend操作

 begin返回的迭代器指向容器中的第一個元素,end返回的迭代器指向末端元素的下一個,它指向了一個容器中不存在的元素。若容器爲空,則beginend返回的迭代器相同。

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是可以變化的:迭代器指向的位置可以發生變化,但迭代器指向的位置的值不能夠發生變化

  Constvector容器的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指向的值了。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章