1. GOF 迭代器設計模式
前面一篇文章有寫到stl_list的實現,也實現了一下相應的iterator,但是后面覺得,實現具體容器之前有必要介紹一下iterator(迭代器) 。那么迭代器是什么呢?
GOF的設計模式是這樣定義的: 提供一種方法順序訪問一個聚合對象中各個元素,而又不需暴露該對象的內部表示。
大概意思是,例如一個聚合對象(list),我們該如何來訪問它的元素,而又不暴露內部結構;而且還要針對不同的需要,可能以不同的方式遍歷這個list;那么即使,我們知道大概會有哪些遍歷操作,那我們也不會希望list接口中充斥着各種不同遍歷操作。一句話,就是如果把遍歷和操作元素的各種方法都放到list中來實現,那么將會導致list類中結構變得混亂而且不穩定。
正好迭代器就是用來提供給外部訪問聚合對象元素的一個結構。 那GOF設計模式,采用的實現方式是OOP(面向對象),類圖關系如下:

具體的聚合對象有自己的繼承關系,具體的iterator也有自己的繼承關系,也就是通過繼承多態來實現用戶側代碼無需修改,就可以兼容不同的聚合對象。在GOF設計模式書中專門有一點提到:使用多態迭代器是有代價的。他們要求用一個Factory Method動態分配迭代器對象。因此僅當必須多態時才使用它們。
2. STL 迭代器
在C++ STL中,也是繼承了GOF提出的迭代器基本需求,並且迭代器(iterator)扮演着重要角色,來將將容器和算法分開,彼此獨立設計,最后再以膠着劑(iterator)將它們撮合在一起。
那么C++ STL實現iterator和GOF介紹的迭代器實現方法什么區別呢? 那首先我們需要了解C++中的兩個編程范式的概念,GP(泛型編程)和OOP(面向對象編程)。
在C++語言里面,我們可以以下方式來簡單區分一下GP和OOP:
GP: 泛型編程,也被稱為"靜態多態",多種數據類型在同一種算法或者結構上皆可操作,其效率與針對某特定數據類型而設計的算法或者結構相同, 具體數據類型在編譯期確定,編譯器承擔更多,代碼執行效率高。在STL中利用GP將methods和datas實現了分而治之。
OOP: 將methods和datas關聯到一起 (通俗點就是方法和成員變量放到一個類中實現),通過繼承的方式,利用虛函數表(virtual)實現運行時類型判定,也叫"動態多態", 由於運行過程中需根據類型去檢索虛函數表,因此效率相對較低。
剛好,C++ STL庫的整個實現采用的就是GP(Generic Programming),而不是OOP(Object Oriented Programming)。而GOF設計模式采用的 就是繼承關系實現的,因此,相對來講,C++ STL的實現效率會相對較高,而且也更有利於維護。
3. STL iterator分類和總結
迭代器類型基本關系:

STL 迭代器基本介紹:
1、輸入迭代器:只讀,一次傳遞
可為輸入迭代器預定義實現只有istream_iterator和istreambuf_iterator,用於從一個輸入流istream中讀取。一個輸入迭代器僅能對它所選擇的每個元素進行一次解析,它們只能向前移動。一個專門的構造函數定義了超越末尾的值。總是,輸入迭代器可以對讀操作的結果進行解析(對每個值僅解析一次),然后向前移動。
2、輸出迭代器:只寫,一次傳遞
這是對輸入迭代器的補充,不過是寫操作而不是讀操作。為輸出迭代器的預定義實現只有ostream_iterator和ostreambuf_iterator,用於向一個輸出流ostream寫數據,還有一個一般較少使用的raw_storage_iterator。他們只能對每個寫出的值進行一次解析,並且只能向前移動。對於輸出迭代器來說,沒有使用超越末尾的值來結束的概念。總之,輸出迭代器可以對寫操作的值進行解析(對每一個值僅解析一次),然后向前移動。
3、前向迭代器:多次讀/寫
前向迭代器包含了輸入和輸出迭代器兩者的功能,加上還可以多次解析一個迭代器指定的位置,因此可以對一個值進行多次讀/寫。顧名思義,前向迭代器只能向前移動。沒有為前向迭代器預定義迭代器。
4、雙向迭代器:operator--雙向迭代器具有前向迭代器的全部功能。另外它還可以利用自減操作符operator--向后一次移動一個位置。由list容器中返回的迭代器都是雙向的。
5、隨機訪問迭代器:類似於一個指針隨機訪問迭代器具有雙向迭代器的所有功能,再加上一個指針所有的功能(一個指針就是一個隨機訪問迭代器),除了沒有一種“空(null)”迭代器和空指針對應。基本上可以這樣說,一個隨機訪問迭代器就像一個指針那樣可以進行任何操作,包括使用操作符operator[]進行索引,加某個數值到一個指針就可以向前或者向后移動若干個位置,或者使用比較運算符在迭代器之間進行比較。
可以參考一下之前list實現的iterator代碼,iterator內部維護一個list節點指針,然后對++和--進行操作符重載時,其實是指針的前后移動,因此stl_list的迭代器類型為雙向迭代器。

迭代器作為STL的一個重要組成部分,今天算是做了一個簡單的總結,在后續分析STL其他內容的過程中也會經常遇到!
2018年9月25日23:44:02
