小古銀的官方**(完整教程):
本部分教程將講解迭代器的使用,這樣就可以更靈活地使用c++的容器庫和演算法庫。設計迭代器將留到高階教程中講解。
在前面排序的教程中,曾經使用過迭代器,迭代器為演算法庫和容器庫之間的操作提供了通用的方案,使得我們使用它們的時候非常方便。
我們熟悉的字串類和std::vector
都有很多成員函式需要或者返回迭代器。例如前面排序用到的成員函式begin()
和end()
就是返回第乙個位置和最後乙個位置的迭代器,然後給std::sort()
函式呼叫;還有就是std::vector
的insert()
和erase()
都是必須以迭代器作為引數來操作。
如果指標儲存靜態陣列位址,那麼這個指標也算是乙個迭代器,例如下面的指標p
。
int array[10]{};
int *p = array + 4;
像上面的指標p
儲存了array[4]
的位址。因為指標儲存了這個陣列中某個元素的位址,我們知道靜態陣列中的位址是連續的,也就是說這個指標相當於儲存了這個陣列的某個元素的位置,然後可以通過*
對位址代表的記憶體進行操作。
接著這個指標還可以通過++
來移動到下個元素的位置,也可以通過--
來移動到上個元素的位置。
int array[10]{};
int *p = array + 4;
++p; // 移動到下乙個元素, 就是array[5]的位置
++p; // 移動到下乙個元素, 就是array[6]的位置
++p; // 移動到下乙個元素, 就是array[7]的位置
--p; // 移動到上乙個元素, 就是array[6]的位置
*p = 666; // 給當前位置的元素賦值為666
像這樣,可以逐個元素按順序地移動指標就是迭代,這就是迭代器(英文:iterator)這個名稱的由來。
而我們使用的迭代器大部分都是類,這些迭代器類的用法,會盡量保持和指標一樣的操作,所以我們可以像指標那樣使用迭代器。更具體的用法在接下來的教程中慢慢講解,這裡不需要太深入了解,只要看了後面講解的使用方法,就會很容易明白迭代器是什麼了。
迭代器基本上都是專用的,如std::vector
的迭代器不能用來儲存std::string
的元素位置,如下,去掉最後兩行開頭注釋將會編譯報錯:
std::vector::iterator iter1; // std::vector的迭代器
std::vector::iterator iter2; // std::vector的迭代器
std::string::iterator iter3; // std::string的迭代器
// iter1 = iter2; // std::vector和std::vector不是同一種型別
// iter1 = iter3; // std::vector和std::string不是同一種型別
但是所有的迭代器都會統一操作,遮蔽了這些操作的細節,使得我們每次都可以用相同的方法操作迭代器。例如我們使用迭代器的時候使用++
,就會使迭代器指向下乙個元素,但是迭代器類內部的**不一定是寫了++
,有可能是其他。
因為迭代器統一了操作,所以演算法庫就可以很輕鬆地操作各種不同的容器了。
標準迭代器有五種:
程式經常會用到容器,而使用容器基本上離不開使用迭代器。只是使用迭代器的話,暫時不需要精通迭代器,但是基本的規則是要知道的。
std::list::iterator iter1; // std::list的迭代器是雙向迭代器
std::vector::iterator iter2; // std::vector的迭代器是隨機訪問迭代器
iter2 += 4; // 允許隨機訪問任何的元素, 這裡是直接跳到這個元素後的第四個元素的位置
++iter1; // 雙向迭代器只支援++和--操作
// iter1 += 4; // 雙向迭代器不支援隨機訪問, 也就是不能跳著訪問其他元素
容器std::vector
使用的是隨機訪問迭代器,例如上面的iter2 += 4;
就是從當前位置跳到它後面的第四個元素的位置上,也可以跳到其他位置,這就是隨機訪問。而std::list
的迭代器是雙向迭代器,它只提供了++
和--
操作,所以iter1 += 4;
是會編譯報錯的,如果需要iter1
移動到它後面的第四個元素的位置,只能使用四次的++iter1;
。
在說明文件中,都會說明容器的迭代器的種類。如果知道迭代器種類,但不知道這個種類的迭代器怎麼用就很尷尬了。以下列出所有迭代器種類對應的必須提供的操作(假設x
是迭代器資料型別,a
和b
是迭代器變數,n
是整數,t
是值,m
是成員):
種類屬性
示例所有種類
可複製構造、可複製賦值並且可以析構
x b(a);
b = a;
可以遞增
++aa++
隨機訪問
雙向前向
輸入支援相等和不相等的比較操作
a == b
a != b
可以解引用成乙個右值
*aa->m
輸入可以解引用成乙個左值
(前提是允許修改內容的迭代器資料型別)
*a = t
*a++ = t
可以預設構造
x a;
x()無論是解引用還是自增,都不能影響解引用的行為
可以遞減
–aa–
*a–支援算術操作符 + 和 -
a + n
n + a
a - n
a - b
支援 < 、 > 、 <= 和 >= 這些比較操作
a < b
a > b
a <= b
a >= b
支援 += 和 -= 操作
a += n
a -= n
支援偏移解引用操作( )
a[n]
c 入門教程 十五
好久沒敲黑板了 前方高能預警 今天的內容可能有些繞,但是,蠻有用的。至少,好玩。前面我們說過,宣告乙個變數,相當於在記憶體中要了一塊空間。不同型別的變數要的空間的大小是不一樣的。既然有了空間,那麼,它就有個開始的位置 比如學校就有門牌號 我們用符號 來獲取乙個變數的位址。用法如下 要獲取首位址的變數...
C 入門教程(八十) 多重繼承
小古銀的官方 完整教程 多重繼承的呼叫順序 多重繼承的呼叫順序總結 多重繼承就是派生類繼承了多個基類。我們知道繼承可以將基類的所有成員都繼承下來作為自己的成員,重繼承也是一樣。include std cout std endl class base1 class base2 class derive...
C 入門教程(十五) 數字與進製
小古銀的官方 完整教程 補充知識 了解即可 鞏固練習 當你完成上一部分教程的全部練習後,相信你應該可以靈活地使用c 去解決大部分問題,尤其是數學問題。本部分教程將講解c 中必須知道的計算機基礎知識,知道這些知識可以避免不少的錯誤,還可以對程式 進一步優化。由於這部分教程只講解c 需要知道的計算機基礎...