前言
之前的兩篇文章我們主要了解了vector和string的相關(guān)知識,從中我們知道可以通過下標來訪問vector的元素或者string的字符,但是除了這種方式還有一種更為通用的方式獲取元素,那就是迭代器,這篇文章就會簡單介紹迭代器的相關(guān)內(nèi)容。
迭代器簡介
在我們使用容器去存儲元素的時候有時候會需要獲取存儲的元素,而迭代器就是用于從容器中獲取元素的,基本上所有容器的庫都支持迭代器,但是只有其中一小部分支持下標獲取元素的。雖然string不是容器但是其支持很多容器的操作,其中就包括下標和迭代器。
與指針類似,迭代器提供了一種間接獲取對象的方式,對于迭代器而言,這個對象就是容器中的元素或者string中的字符,我們可以通過迭代器獲取一個元素,與此同時也可以將指向的對象從一個對象移到下一個對象。迭代器還和指針一樣有有效和無效之分,所有代表容器中元素或最后一個元素的下一個位置都是有效的,其他所有的迭代器都是無效的。
迭代器的使用
不像指針,我們不使用地址操作符去獲取一個迭代器,每一個支持迭代器的類型都有函數(shù)可以返回迭代器,這些類型都有名為begin和end的函數(shù),begin返回的是代表第一個元素的迭代器,end的返回的迭代器是容器或者字符串的最后一個元素的下一個位置,這個迭代器代表著最后一個元素的下一個位置,是一個不存在的元素。如果容器為空,則begin和end返回的是同一個迭代器。
auto b = v.begin(), e = v.end()
迭代器的操作
迭代器只支持下表列出來的操作,我們可以通過==或!=比較兩個有效的迭代器,如果迭代器代表著同一個元素或者都是最后一個元素的下一個位置則相等,否則它們不等。 |操作|解釋| |*iter|返回迭代器代表的指針指向的值| |iter->mem|等價于(*iter).mem| |++iter|指向容器中的下一個元素| |--iter|指向容器中的前一個元素| |iter1 == iter2|判斷兩個迭代器是否相等| |iter1 != iter2|判斷兩個迭代器是否不等|
對于指針,我們可以使用解引用符獲取一個迭代器的元素,和指針相同,我們只能通過解引用符獲取一個有效的迭代器的元素,如果解引用一個最后一個元素之后的迭代器結(jié)果是未知的。
# include
# include
using namespace std;
int main() {
string s("some string");
if (s.begin() != s.end()) {
auto it = s.begin();
*it = toupper(*it);
}
cout<
上述的例子就是通過迭代器獲取字符串s的首個字符并將其大寫。
迭代器從一個元素移動到另一個元素
迭代器私用自增操作符從一個元素移動到該元素的下一個元素,自增一個迭代器與自增一個整型十分類似,對于整型而言,自增的是其本身的值,對于迭代器而言,其影響是往前進一個位置。
?由于end返回的不是一個元素,所以其不能自增或者解引用
?
使用自增操作我們可以重寫之前的程序:
# include
# include
using namespace std;
int main() {
string s("some string");
for (auto it = s.begin(); it != s.end() && !isspace(*it); ++it) {
*it = toupper(*it);
}
cout<
如上例所示,我們通過迭代器可以實現(xiàn)循環(huán)遍歷。
迭代器的類型
正如我們并不準確知道vector的準確類型或者string的size,同樣的,我們也不知道同時也不需要知道迭代器的準確類型,但是根據(jù)迭代器的讀寫權(quán)限定義了以下幾種迭代器的類型:
vector<int>::iterator it; //it可以讀也可以寫vector
string::iterator it2; //it2可以讀寫字符串里的字符
vector<int>::const_iterator it3; //it3可以讀但是不可以寫元素
string::const_iterator it4; //it4可以讀但是不可以寫字符串里面的字符
const_iterator表現(xiàn)就像是常量指針,可以讀取元素但是不能寫元素
begin和end操作
begin和end返回的結(jié)果取決于它們操作的對象是不是常量,如果操作對象是常量,那么begin和end返回的就是const_iterator,如果對象不是常量,那么返回的就是iterator。
# include
# include
# include
using namespace std;
int main() {
vector<int> v;
const vector<int> cv;
auto it1 = v.begin(); //it返回的是vector
auto it2 = v.begin(); //it返回的是vector
}
這種默認的返回策略有時候并不滿足需求,在一些情況下一些非常量的vector我們只想讀取元素,避免元素被更改,在C++11中提供了以下新的方法cbegin和cend,無論vetor是不是常量都返回const_iterator。
auto it3 = v.cbegin();
迭代器的數(shù)學(xué)運算
處理之前提到自增和自減外,迭代器還支持以下數(shù)學(xué)運算,雖然迭代器是沒有下標的概念的,但是一下運算都可以理解為是對于下標的操作,如加減就是自增和自減的普通形式,就是向前移動或者向后移動,大小比較就是前后位置的比較。
操作 | 解釋 |
---|---|
iter + n | 同一個容器向前移動n |
iter - n | 同一個容器向后移動 |
iter1 += n | 將移動結(jié)果賦值給iter1 |
iter1 -= n | 將移動結(jié)果賦值給iter1 |
>, >=, <, <= | 相對位置的比較 |
這么說起來可能又帶你抽象,下面用一個二分法來說明:
# include
# include
# include
using namespace std;
int main() {
vector<int> v = {1, 2, 3, 4, 5};
auto beg = v.begin(), end = v.end();
auto mid = v.begin() + (end - beg) / 2;
int target = 2;
while (mid != end && *mid != target)
{
if (target < *mid) {
end = mid;
} else{
beg = mid;
}
mid = beg + (end - beg) / 2;
}
cout<<to_string(*mid)<
以上例子會打印2,也就是元素2的位置。
-
C++
+關(guān)注
關(guān)注
22文章
2104瀏覽量
73495 -
Vector
+關(guān)注
關(guān)注
3文章
56瀏覽量
8556 -
迭代器
+關(guān)注
關(guān)注
0文章
43瀏覽量
4302
發(fā)布評論請先 登錄
相關(guān)推薦
評論