迭代器是一種檢查容器內元素並遍歷元素的數據類型。C++更趨向於使用迭代器而不是下標操作,因為標准庫為每一種標准容器(如vector)定義了一種迭代器類型,而只用少數容器(如vector)支持下標操作訪問容器元素。
一.定義和初始化
每種容器都定義了自己的迭代器類型,如vector:
vector<int>::iterator iter; //定義一個名為iter的變量
每種容器都定義了一對名為begin和en的函數,用於返回迭代器。下面對迭代器進行初始化操作:
vector<int> ivec; vector<int>::iterator iter1=ivec.bengin(); //將迭代器iter1初始化為指向ivec容器的第一個元素 vector<int>::iterator iter2=ivec.end(); //將迭代器iter2初始化為指向ivec容器的最后一個元素的下一個位置
注意end並不指向容器的任何元素,而是指向容器的最后元素的下一位置,稱為超出末端迭代器。如果vector為空,則begin返回的迭代器和end返回的迭代器相同。一旦向上面這樣定義和初始化,就相當於把該迭代器和容器進行了某種關聯,就像把一個指針初始化為指向某一空間地址一樣。
二.常用操作
下面列出了迭代器的常用運算操作:
*iter //對iter進行解引用,返回迭代器iter指向的元素的引用 iter->men //對iter進行解引用,獲取指定元素中名為men的成員。等效於(*iter).men ++iter //給iter加1,使其指向容器的下一個元素 iter++ --iter //給iter減1,使其指向容器的前一個元素 iter-- iter1==iter2 //比較兩個迭代器是否相等,當它們指向同一個容器的同一個元素或者都指向同同一個容器的超出末端的下一個位置時,它們相等 iter1!=iter2
假設已經聲明一個vector<int>的ivec容器,下面用迭代器來遍歷ivec容器,把其每個元素重置為0:
for(vector<int>::iterator iter=ivec.begin();iter!=ivec.end();++iter) *iter=0;
在C++定義的容器類型中,只有vector和queue容器提供迭代器算數運算和除!=和==之外的關系運算:
iter+n //在迭代器上加(減)整數n,將產生指向容器中錢前面(后面)第n個元素的迭代器。新計算出來的迭代器必須指向容器中的元素或超出容器末端的下一個元素 iter-n iter1+=iter2 //將iter1加上或減去iter2的運算結果賦給iter1。兩個迭代器必須指向容器中的元素或超出容器末端的下一個元素 iter1-=iter2 iter1-iter2 //兩個迭代器的減法,得出兩個迭代器的距離。兩個迭代器必須指向容器中的元素或超出容器末端的下一個元素 >,>=,<,<= //元素靠后的迭代器大於靠前的迭代器。兩個迭代器必須指向容器中的元素或超出容器末端的下一個元素
注意兩個迭代器相減得出兩個迭代器對象的距離,該距離名為difference_type的signed類型的值,該類型類似於size_type類型,也是有vector定義的。可以迭代器算術操作來移動迭代器直接指向某個元素:
vector<int>::iterator mid=v.begin()+v.size()/2; //初始化mid迭代器,使其指向v中最靠近正中間的元素
三.迭代器const_iterator
每種容器還定義了一種名為const_iterator的類型。該類型的迭代器只能讀取容器中的元素,不能用於改變其值。之前的例子中,普通的迭代器可以對容器中的元素進行解引用並修改,而const_iterator類型的迭代器只能用於讀不能進行重寫。例如可以進行如下操作:
for(vector<int>::const_iterator iter=ivec.begin();iter!=ivec.end();++iter) cout<<*iter<<endl; //合法,讀取容器中元素值 for(vector<int>::const_iterator iter=ivec.begin();iter!=ivec.end();++iter) *iter=0; //不合法,不能進行寫操作
const_iterator和const iterator是不一樣的,后者對迭代器進行聲明時,必須對迭代器進行初始化,並且一旦初始化后就不能修改其值。這有點像常量指針和指針常量的關系。例如:
vector<int> ivec(10); const vector<int>::iterator iter=ivec.begin(); *iter=0; //合法,可以改變其指向的元素的值 ++iter; //不合法,無法改變其指向的位置
四.使迭代器失效的操作
由於一些對容器的操作如刪除元素或移動元素等會修改容器的內在狀態,這會使得原本指向被移動元素的迭代器失效,也可能同時使其他迭代器失效。使用無效的迭代器是沒有定義的,可能會導致和使用懸垂指針相同的問題。所以在使用迭代器編寫程序時,需要特別留意哪些操作會使迭代器失效。使用無效迭代器會導致嚴重的運行時錯誤。
參考文獻
《C++ PRIMER》 中文版