💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤
📃個人主頁 :阿然成長日記 👈點擊可跳轉
📆 個人專欄: 🔹數據結構與算法🔹C語言進階🔹C++
🚩 不能則學,不知則問,恥于問人,決無長進
🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍
文章目錄
- 前言
- 對string對象的訪問接口
- 1.oparator[]
- 2.at()
- 3.迭代器iterators
- (1)begin和end
- 💤中途休息~問題思考
- (2)rbegin和rend
- 3.范圍for
- 4.back和front
前言
上一篇文章中講解了關于string類,以及相關的默認函數,容量有關的接口的學習。本篇博客繼續對string接口進行講解 。其中迭代器的講解是重中之重。
對string對象的訪問接口
- 1.下標訪問
oparator[]
- 2.
at()
, - 3.迭代器
iterators
, - 4.
范圍for
, - C++11中的5.
back
和6.front
1.oparator[]
- 簡單來說就是通過類似于數組的訪問方式,來對字符串進行訪問以及增,刪等操作。
如下:
- 這種方法比較簡單常用。上面這種string[]的形式和下面這樣對字符數組的訪問是有本質區別的。
其底層依然是調用了operator[],而普通的數組[]實際上是一種解引用。
如下兩幅圖所示👇,
查看反匯編:
由此可以證明,string類使用[]
時其底層依然是調用了operator[]
,而普通的數組[]
實際上是一種解引用
。
2.at()
同樣有兩個重載,一個是普通對象,一個則是const對象
使用:
- 可以看到,他的使用方式也是十分簡單。
下面再來看看處理異常時的情況:👇
int main()
{string s1("hello world!");1.s1.at(20)++;2.s1[20]++;return 0;
}
-
1.使用
at()
的運行結果是:拋出異常!
-
2.使用
oparator[]
的運行結果是:產生了一個越界訪問的話就直接報出【斷言錯誤】
3.迭代器iterators
迭代器(iterator)
是一種可以遍歷容器元素的數據類型。迭代器是一個變量,相當于容器和操縱容器的算法之間的中介。C++更趨向于使用迭代器而不是數組下標操作,因為標準庫為每一種標準容器(如vector、map和list等)定義了一種迭代器類型,而只有少數容器(如vector)支持數組下標操作訪問容器元素。可以通過迭代器指向你想訪問容器的元素地址,通過*x打印出元素值。這和我們所熟知的指針極其類似。
————————————————
??問題1:迭代器到底是什么?
答C++迭代器是一種用于遍歷容器中元的對象。它提供了一種統一的訪問容器元素的方式,無論容器的類型如何,都可以使用相同的語法進行操作。
迭代器的本質是一個指針,它指向容器中的某個元素。通過迭代器,我們可以訪問容器中的元素,并且可以對元素進行修改、刪除或插入操作。迭代器可以分為正向迭代器和反向迭代器,分別用于從容器的起始位置向后遍歷和從容器的末尾位置向前遍歷。
迭代器的實現方式取決于容器的類型。對于數組和指針類型的容器,迭代器本質上就是指針,通過指針的加減運算來實現遍歷。對于其他類型的容器,如vector、list等,迭代器是一個包含指向容器元素的指針以及一些操作函數的對象。
- 總結來說,C++迭代器的本質是一個指針,它提供了一種統一的訪問容器元素的方式,使得我們可以方便地遍歷和操作容器中的元素。iterator提供一種統一的方式訪問和修改容器。
接口匯總
接口 | 作用 |
---|---|
begin | 將迭代器返回到開頭 |
end | 返回迭代器以結束 |
rbegin | 返回反向迭代器以反向開始 |
rend | 將反向迭代器返回到反向端 |
cbegin | 返回const_iterator開頭 |
cend | 返回const_iterator結束 |
crbegin | 返回const_reverse_iterator以反轉開始 |
crend | 返回const_reverse_iterator反轉端 |
(1)begin和end
同樣有兩個重載,一個是普通對象,一個則是const對象
begin
:獲取一個字符的迭代器end
:獲取最后一個字符下一個位置的迭代器
實例操作:
string::iterator it = s1.begin();
- 每個容器(ist,vector,map等等)里都有iterator迭代器,所以我們要在iterator前加上作用域(當然也可以加
auto
去自動匹配類型)。 it
取到的是每個元素的位置,那么對于*it
來說即為每個元素。- 使用
正向
迭代器接收iterator
.還會有反向迭代器,馬上會講。
💤中途休息~問題思考
那么,如果使用const對象呢?
- 使用const修飾的迭代器接收:
- 傳入const修飾的對象的引用
通過上圖可以發現,const修飾后,都不能進行修改指向的元素值。
- 還有重要的一點,在一個函數中,通常使用迭代器遍歷封裝為函數,采取
引用傳值
減少拷貝構造,再加上const做修飾,防止權限放大。還必須使用const_iterator
接收,如下圖👇:
- 正確的做法是使用
const_iterator
接收👇
(2)rbegin和rend
rbegin
:指向的是最后一個字符的位置rend
: 指向的是第一個字符的前一個位置
實例操作:使用反向迭代器接收reverse_iterator
小結:
四種迭代器:
可讀不可改 | const_iterator 和 const_reverse_iterator |
---|---|
可讀可改 | iterator 和 reverse_iterator |
🚩一定一定注意權限問題!!!
3.范圍for
格式:for (type val:
iterable
);
使用:
int main()
{string s1("hello world!");for (char val : s1){cout << val << " ";}return 0;
}
執行結果:
- 在增強for循環中,我們不需要再通過計算數組長度遍歷數組,增強for循環會自動根據數組長度將數組中的每一個數據賦值給同類型的val,我們只需要輸出val就遍歷了數組。
iterable
不止可以為數組,還可以是迭代的對象(比如支持begin、end操作的容器、string類型等)- 范圍for的底層實現還是
迭代器
,所以我們可以說在它在遍歷的時候相當于是將*it
的數據給到當前的val
,與迭代器十分相似。
還有十分要的一點,注意這個val他是一個拷貝。最好進行傳引用,可以減少拷貝構造。以及多次析構等問題。
4.back和front
front
:取到的是字符串的首字符back
:取到的則是字符串的尾字符
注意:直接取到元素。