2011-04-09 53 views
5

嗨所以我對於迭代器有點迷茫,他們實際上是....在C++ STL瞭解迭代

在這種情況下即時通訊使用的名單,我不明白爲什麼你有什麼做一個迭代器:
std::list <int>::const_iterator iElementLocator;

由derefrence運營商dipslay列表的內容:
cout << *iElementLocator;

賦予它也許list.begin後();

請解釋什麼是一個迭代器,爲什麼我必須去除它/使用它!
謝謝!

回答

10

有在STL三大基石:

  • 集裝箱
  • 算法
  • 迭代

在概念層次的容器保存數據。這本身並不是很有用,因爲你想東西與數據;你想上運行,操縱它,查詢它,玩它。算法就是這樣做的。但算法不會保存數據,他們沒有數據 - 他們需要一個容器來完成這個任務。給容器一個算法,你有一個動作在進行。

要解決的唯一問題是,從技術角度來看,算法如何遍歷一個容器。從技術上講,一個容器可以是一個鏈表,也可以是一個數組,或二叉樹,或任何其他可以容納數據的數據結構。但遍歷一個數組的方式與遍歷二叉樹不同。儘管在概念上所有算法都需要從容器中一次「獲取」一個元素,然後處理該元素,但從容器中下一個元素的操作在技術上非常容器特定。

看起來好像您需要爲每個容器編寫相同的算法,以便每個版本的算法都具有正確的遍歷容器的代碼。但是有一個更好的解決方案:請容器返回一個可以遍歷容器的對象。該對象將有一個接口算法知道。當算法要求對象「獲取下一個元素」時,該對象將符合。由於對象直接來自容器,因此知道如何訪問容器的數據。並且由於該對象具有該算法知道的接口,所以我們不需要爲每個容器重複一個算法。

這是迭代器。

迭代器在這裏該算法的容器,沒有耦合的兩個。一個迭代器被耦合到一個容器,並且一個算法被耦合到迭代器的接口。這裏的魔法來源真的是模板編程。考慮標準copy()算法:

template<class In, class Out> 
Out copy(In first, In last, Out res) 
{ 
    while(first != last) { 
     *res = *first; 
     ++first; 
     ++res; 
    } 
    return res; 
} 

copy()算法作爲參數模板的類型InOut類型的一個迭代兩個迭代。它將從位置first開始並在位置last之前結束的元素複製到res中。算法知道獲得下一個元素需要說++first++res。它知道要讀取一個元素,它需要說x = *first並寫一個元素,它需要說*res = x。這是接口算法假設和迭代器承諾的一部分。如果錯誤的迭代器不符合接口,那麼當類型未定義函數時,編譯器將通過類型InOut發出調用函數的錯誤。

+0

+1很好的解釋。 – Nawaz 2011-04-09 19:29:03

0

已經存在很多很好的迭代器解釋。只是谷歌它。

一個example

如果有什麼具體的東西你不明白回來問。

+5

堆棧溢出問題經常成爲谷歌的熱門話題,此時回答說:「爲什麼不穀歌呢」看起來相當短視。 http://meta.stackexchange.com/questions/5280/embrace-the-non-googlers – 2011-04-09 18:39:20

6

我很懶。因此,我不會鍵入描述什麼是迭代器以及它們是如何使用的,尤其是當已經有很多在線文章可供您閱讀時。

這裏有一些,我可以引述一開始,proividing的鏈接來完成的文章:

MSDN說,

迭代器是 指針的推廣,從他們的 要求抽象一種允許C++程序以統一的方式與不同的 數據結構一起工作的方式。 迭代器充當容器和通用 算法之間的中介 。而不是在 特定數據類型上運行,算法是 定義爲在由迭代器類型指定的範圍 上操作。滿足迭代器的 要求的任何 數據結構然後可以由算法操作 。有 五種類型或 迭代器的類別[...]

順便說一句,似乎MSDN採取了文本加粗從C++標準本身,特別是從部分§24.1/ 1,它說:

迭代是 指針,其允許C++程序與以均勻的方式不同的數據結構 (容器) 工作的概括。爲了 能夠構建模板 算法正確 有效地工作在不同類型的數據 結構,圖書館正式確定不 只是接口也是 語義和複雜的假設迭代 。所有迭代器我支持 表達式* i,導致某個類,枚舉或 內置類型T的值爲 ,稱爲迭代器的值類型 。所有用於 的迭代器i其表達式(* i).m爲 ,定義明確,支持表達式 i-> m,其語義與 (* i).m相同。對於 的每個迭代類型X,定義了相等性,將有一個 對應的有符號整數類型 ,稱爲 迭代器的差異類型。

cplusplus說,

在C++中,一個迭代是任何對象 的是,指向一些元件在 範圍的元素(如數組或 的容器)的,有能力到 使用一組運算符(至少爲 ,增量(++)和 解除引用(*)運算符)遍歷該 範圍的元素。

迭代器的最明顯的形式是 指針[...]

而且你還可以閱讀這些:

請耐心等待並閱讀所有這些內容。希望你在C++中能夠知道迭代器是什麼。學習C++需要耐心和時間。

0

我建議閱讀關於在C++中的運算符重載。這將說明爲什麼*->基本上可以表示任何事情。只有這樣你才能閱讀關於迭代器的內容。否則,它可能會顯得非常混亂。

2

迭代器是一個STL容器,指針指向一個數組。您可以將它們視爲STL容器的指針對象。作爲指針,您可以使用指針表示法(例如*iElementLocator,iElementLocator++)。作爲對象,他們將擁有自己的屬性和方法(http://www.cplusplus.com/reference/std/iterator)。

1

迭代器與容器本身不一樣。迭代器引用容器中的單個項目,並提供到達其他項目的方法。

考慮設計你自己的沒有迭代器的容器。它可以有一個size函數來獲取它包含的項目數量,並且可以使[]運算符超載,以允許您通過其位置獲取或設置項目。

但是這種「隨機存取」在某些種類的容器上不易實現。如果您獲得第百萬個項目:c[1000000]並且容器在內部使用鏈接列表,則必須掃描一百萬個項目才能找到您想要的項目。

您可能決定允許集合記住「當前」項目。它可以像startmorenext功能,讓您可以遍歷內容:

c.start(); 
while (c.more()) 
{ 
    item_t item = c.next(); 

    // use the item somehow 
} 

但是這使容器內的「迭代狀態」。這是一個嚴重的限制。如果您想將容器中的每件商品與其他商品進行比較,該怎麼辦?這需要兩個嵌套循環,遍歷所有項目。如果容器本身存儲迭代的位置,則無法嵌套兩個這樣的迭代 - 內部循環將會破壞外部循環的工作。

所以迭代器是一個迭代狀態的獨立副本。就可以開始迭代:

container_t::iterator i = c.begin(); 

即迭代器,i,是一個獨立的對象,表示在容器內的位置。您可以獲取任何存儲在該位置:

item_t item = *i; 

你可以移動到下一個項目:

i++; 

有了一些迭代器,你可以跳過前幾個項目:

i += 1000; 

或者獲取相對於迭代器標識的位置的某個位置的項目:

item_t item = i[1000]; 

並且有些迭代器可以向後移動。

,您可以通過迭代比較end發現,如果你已經超過容器的內容達成:

while (i != c.end()) 

你能想到的end爲返回,表示一個位置,是一個超越的迭代器容器中的最後一個位置。

使用迭代器(通常在C++中)要注意的一個重點是它們可能會失效。例如,如果您清空容器,通常會發生這種情況:指向該容器中位置的任何迭代器現在都變得無效。在那個狀態下,他們的大部分操作都是未定義的 - 任何事情都可能發生!