C++ STL之迭代器

SJLin96發表於2018-08-23

一. 什麼是迭代器?

  • 迭代器是STL中行為類似指標的設計模式,它可以提供了一種對容器中的物件的訪問方法;並且它沒有暴露容器中內部的表述方式。 
  • 例如STL中的map和set,它們的底層是一顆紅黑樹(一種平衡樹),而當你用迭代器去對他們進行訪問時,原本在紅黑樹中的二叉樹結構卻能轉換成一種線性結構的訪問方式,如上述例子。
  • 也就是說,迭代器提供了一種一般化的方法對順序或關聯容器型別中的每個元素進行連續訪問。
  • 可見,迭代器既能對容器中的物件進行訪問,又能將容器的結構隱藏起來,達到封裝的效果。
  • 所有容器有含有其各自的迭代器型別(iterator types),所以當你使用一般的容器迭代器時,並不需要含入專門的標頭檔案。不過有幾種特別的迭代器,例如逆向迭代器,被定義於<iterator>中。

 

  • 迭代器可以看做一種智慧指標,他會過載*和->運算子。但是它並不一定具備指標的所有運算子:p++,p--,p+n,p-n,p[n],p1-p2,p1<p2,p1!=p2。有可能它只提供一部分,比如:p++,p--,p1!=p2。
  • STL強資料容器與演算法分開,而迭代器又作為膠著劑將其撮合在一起。幾乎STL提供的所有演算法都是通過迭代器存取元素序列進行工作的,每一個容器都定義了其本身所專有的迭代器,用以存取容器中的元素。

 

  • 每種容器還定義了一種名為const_iterator的型別。該型別的迭代器只能讀取容器中的元素,不能用於改變其值。
  • 由於一些對容器的操作如刪除元素或移動元素等會修改容器的內在狀態,這會使得原本指向被移動元素的迭代器失效,也可能同時使其他迭代器失效。使用無效的迭代器是沒有定義的,可能會導致和使用懸垂指標相同的問題。所以在使用迭代器編寫程式時,需要特別留意哪些操作會使迭代器失效。使用無效迭代器會導致嚴重的執行時錯誤。

 

二. 怎麼用迭代器?

1. 定義和初始化

  • 每種容器都定義了自己的迭代器型別,如vector:
vector<int>::iterator    iter;    //定義一個名為iter的變數
  • 每種容器都定義了一對名為begin和end的函式,用於返回迭代器。下面對迭代器進行初始化操作:
vector<int>    ivec;
vector<int>::iterator    iter1=ivec.bengin();    //將迭代器iter1初始化為指向ivec容器的第一個元素

vector<int>::iterator   iter2=ivec.end();    //將迭代器iter2初始化為指向ivec容器的最後一個元素的下一個位置
  • 注意end並不指向容器的任何元素,而是指向容器的最後元素的下一位置,稱為超出末端迭代器。如果vector為空,則begin返回的迭代器和end返回的迭代器相同。一旦向上面這樣定義和初始化,就相當於把該迭代器和容器進行了某種關聯,就像把一個指標初始化為指向某一空間地址一樣。

 

2. 常用操作

*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;

 

參考文章:

【STL】迭代器

STL中的Iterator

C++迭代器的使用和操作總結

相關文章