C++迭代器

迭代器

標(biāo)準(zhǔn)庫(kù)容器類型上所有迭代器都允許我們?cè)L問(wèn)容器中的元素,下面的表中列出了容器迭代器支持的所有操作揍异,其中有一個(gè)例外:forward_list迭代器不支持遞減運(yùn)算符。

迭代器操作 說(shuō)明
*iter 返回迭代器所指元素的引用
iter->member 解引用iter并獲取該元素的名為member的成員爆班,等價(jià)于(*iter).member
++iter 令iter指向容器中下一個(gè)元素
--iter 令iter指向容器中上一個(gè)元素
iter1 == iter2 判斷兩個(gè)迭代器是否指向的是同一個(gè)元素或者是同一個(gè)容器的尾后迭代器
iter1 != iter2 同上

容器中的begin和end迭代器指示了容器中的元素范圍衷掷,其中end迭代器不指向最后一個(gè)元素,而是指向尾元素之后的位置柿菩,這種元素范圍被稱為左閉合區(qū)間:[begin,end)戚嗅,假設(shè)begin和end構(gòu)成了一個(gè)合法的迭代器范圍,則:

  • 如果begin與end相等,則范圍為空懦胞。
  • 如果begin與end不等替久,則范圍至少包含一個(gè)元素,且begin指向該范圍中的第一個(gè)元素躏尉。
  • 我們可以對(duì)begin遞增若干次使得begin==end蚯根。

begin和end有多個(gè)版本,其中帶r的版本返回反向迭代器胀糜,c開(kāi)頭的版本返回const迭代器颅拦。

使用迭代器遍歷數(shù)組:

int main()
{
    int values1[] = { 1,2,3,4,5 };
    for (auto it = begin(values1); it != end(values1); it++) {
        cout << *it << endl;
    }
    system("pause");
}

插入迭代器

插入迭代器是一種迭代器適配器,它接受一個(gè)容器教藻,生成一個(gè)迭代器距帅,能實(shí)現(xiàn)向給定容器添加元素,當(dāng)我們給一個(gè)插入迭代器賦值時(shí)括堤,迭代器調(diào)用容器操作來(lái)向給定容器的指定位置插入一個(gè)元素碌秸,插入完成后迭代器保持不變。*it,++it,it++不會(huì)對(duì)插入迭代器做任何事情痊臭,每個(gè)操作都返回it哮肚。

插入迭代器有三種類型:

  • back_inserter,創(chuàng)建一個(gè)使用push_back的迭代器广匙。
  • front_inserter允趟,創(chuàng)建一個(gè)使用push_front的迭代器。
  • inserter創(chuàng)建一個(gè)使用insert的迭代器鸦致,此函數(shù)接受第二個(gè)參數(shù)潮剪,這個(gè)參數(shù)必須是一個(gè)指向給定容器的迭代器,元素將被插入到給定迭代器所表示的元素之前分唾。
int main()
{
    vector<int> values{ 1,2,3,4 };
    list<int> list1, list2,list3;
    copy(values.cbegin(), values.cend(), back_inserter(list1));
    copy(values.cbegin(), values.cend(), front_inserter(list2));
    copy(values.cbegin(), values.cend(), inserter(list3,list3.begin()));
    for (const auto& e : list1) {
        cout << e << endl;//1 2 3 4
    }
    for (const auto& e : list2) {
        cout << e << endl;//4 3 2 1
    }
    for (const auto& e : list3) {
        cout << e << endl;//1 2 3 4
    }
    system("pause");
}

iostream迭代器

雖然iostream不是容器抗碰,但標(biāo)準(zhǔn)庫(kù)定義了可以用于這些IO類型對(duì)象的迭代器,istream_iterator讀取輸入流绽乔,ostream_iterator向一個(gè)輸出流寫(xiě)數(shù)據(jù)弧蝇,這些迭代器將它們對(duì)應(yīng)的流當(dāng)作一個(gè)特定類型的元素序列來(lái)處理,通過(guò)使用流迭代器折砸,我們可以用泛型算法從流對(duì)象讀取數(shù)據(jù)或?qū)懭霐?shù)據(jù)看疗。

創(chuàng)建一個(gè)流迭代器時(shí),必須指定迭代器將要讀寫(xiě)的對(duì)象類型睦授,還可以將流迭代器綁定到一個(gè)流两芳,如果不綁定它將是一個(gè)可以當(dāng)作尾后值使用的流迭代器。一旦關(guān)聯(lián)的流遇到文件尾或遇到IO錯(cuò)誤去枷,迭代器的值就與尾后迭代器相等怖辆。

int main()
{
    vector<int> values;
    istream_iterator<int> inIter(cin);
    istream_iterator<int> eof;
    while (inIter != eof) {
        //先調(diào)用后置遞增運(yùn)算符是复,然后對(duì)迭代器的舊值進(jìn)行解引用
        values.push_back(*inIter++);
    }
    for (const auto& e : values) {
        cout<<e<<endl;
    }
    system("pause");
}

我們可以將上面的代碼重寫(xiě)為如下形式,values構(gòu)造時(shí)從cin讀取數(shù)據(jù)竖螃,直到遇到文件尾或者不是int的數(shù)據(jù)為止淑廊。

int main()
{
    istream_iterator<int> inIter(cin), eof;
    vector<int> values(inIter, eof);
    for (const auto& e : values) {
        cout<<e<<endl;
    }
    system("pause");
}

由于算法使用迭代器操作來(lái)處理數(shù)據(jù),而流迭代器又至少支持某些迭代器操作斑鼻,因此我們可以使用某些算法來(lái)操作流迭代器蒋纬,下面的代碼計(jì)算從輸入流讀取的值的和。

int main()
{
    istream_iterator<int> inIter(cin), eof;
    cout << accumulate(inIter, eof, 0) << endl;
    system("pause");
}

當(dāng)我們將一個(gè)istream_iterator綁定到一個(gè)流時(shí)坚弱,標(biāo)準(zhǔn)庫(kù)并不保證迭代器立即從流讀取數(shù)據(jù)蜀备,具體實(shí)現(xiàn)可以推遲從流中讀取數(shù)據(jù),標(biāo)準(zhǔn)庫(kù)保證的是在我們解引用迭代器之前荒叶,從流中讀取的操作已經(jīng)完成了碾阁。

int main()
{
    vector<int> values;
    istream_iterator<int> inIter(cin);
    //輸入一個(gè)值后才會(huì)顯示ready now
    cout << "ready now" << endl;
    values.push_back(*inIter);
    system("pause");
}

當(dāng)創(chuàng)建一個(gè)ostream_iterator時(shí),我們可以提供(可選的)第二個(gè)參數(shù)些楣,它是一個(gè)C風(fēng)格字符串脂凶,在輸出每個(gè)元素后都會(huì)打印此字符串。

ostream_iterator必須綁定到一個(gè)流愁茁,*out蚕钦,++out,out++這些運(yùn)算符雖然存在但不對(duì)out做任何事情鹅很,每個(gè)運(yùn)算符都返回out嘶居。

對(duì)ostream_iterator使用賦值運(yùn)算符(=)時(shí),會(huì)用<<運(yùn)算符將等號(hào)右邊的值寫(xiě)入到所綁定的流中促煮,該值的類型必須與流可寫(xiě)的類型兼容邮屁。

int main()
{
    ostream_iterator<int> outIter(cout," ");
    vector<double> values{1.0,2.0,3.0};
    for (const auto& e : values) {
        outIter = e;//1 2 3
    }
    system("pause");
}

還可以通過(guò)copy打印vector中的元素,這比上面的代碼更簡(jiǎn)單菠齿。

int main()
{
    ostream_iterator<int> outIter(cout," ");
    vector<int> values{1,2,3};
    copy(values.cbegin(), values.cend(), outIter);//1 2 3
    system("pause");
}

反向迭代器

反向迭代器就是在容器中從尾元素向首元素反向移動(dòng)的迭代器佑吝,對(duì)于反向迭代器,遞增或遞減的操作含義會(huì)顛倒過(guò)來(lái)绳匀。通過(guò)成員函數(shù)base可以獲得反向迭代器對(duì)應(yīng)的普通迭代器芋忿。

int main()
{
    vector<int> values1 = { 10,2,8,0,9,1 };
    //按逆序排序
    sort(values1.rbegin(),values1.rend());
    ostream_iterator<int> outIter(cout," ");
    copy(values1.cbegin(), values1.cend(), outIter);//10 9 8 2 1 0
    //反向輸出
    copy(values1.crbegin(), values1.crend(), outIter);//0 1 2 8 9 10
    //通過(guò)base()正向輸出
    copy(values1.crend().base(), values1.crbegin().base(), outIter);//10 9 8 2 1 0
    system("pause");
}

移動(dòng)迭代器

移動(dòng)迭代器通過(guò)改變給定迭代器的解引用運(yùn)算符的行為來(lái)適配此迭代器,普通迭代器的解引用運(yùn)算符返回一個(gè)指向元素的左值疾棵,而移動(dòng)迭代器解引用運(yùn)算符生成一個(gè)右值引用盗飒。我們通過(guò)調(diào)用make_move_iterator將普通迭代器轉(zhuǎn)換為一個(gè)移動(dòng)迭代器。

由于移動(dòng)一個(gè)對(duì)象可能銷毀原對(duì)象陋桂,因此只有在確信算法或自定義的函數(shù)使用完元素后不再訪問(wèn)它時(shí),才能將移動(dòng)迭代器傳遞過(guò)去蝶溶。

在庫(kù)代碼中使用移動(dòng)操作(std::move,make_move_iterator)能提升性能嗜历,但是如果在用戶代碼中隨意使用移動(dòng)操作宣渗,很可能會(huì)導(dǎo)致莫名其妙,難以查找的錯(cuò)誤梨州。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末痕囱,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子暴匠,更是在濱河造成了極大的恐慌鞍恢,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件每窖,死亡現(xiàn)場(chǎng)離奇詭異帮掉,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)窒典,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門蟆炊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人瀑志,你說(shuō)我怎么就攤上這事涩搓。” “怎么了劈猪?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵昧甘,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我战得,道長(zhǎng)充边,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任贡避,我火速辦了婚禮痛黎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘刮吧。我一直安慰自己湖饱,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布杀捻。 她就那樣靜靜地躺著井厌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪致讥。 梳的紋絲不亂的頭發(fā)上仅仆,一...
    開(kāi)封第一講書(shū)人閱讀 52,696評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音垢袱,去河邊找鬼墓拜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛请契,可吹牛的內(nèi)容都是我干的咳榜。 我是一名探鬼主播夏醉,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼涌韩!你這毒婦竟也來(lái)了畔柔?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤臣樱,失蹤者是張志新(化名)和其女友劉穎靶擦,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體雇毫,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡玄捕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了嘴拢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桩盲。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖席吴,靈堂內(nèi)的尸體忽然破棺而出赌结,到底是詐尸還是另有隱情,我是刑警寧澤孝冒,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布柬姚,位于F島的核電站,受9級(jí)特大地震影響庄涡,放射性物質(zhì)發(fā)生泄漏量承。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一穴店、第九天 我趴在偏房一處隱蔽的房頂上張望撕捍。 院中可真熱鬧,春花似錦泣洞、人聲如沸忧风。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)狮腿。三九已至,卻和暖如春呕诉,著一層夾襖步出監(jiān)牢的瞬間缘厢,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工甩挫, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留贴硫,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓伊者,卻偏偏與公主長(zhǎng)得像夜畴,于是被迫代替她去往敵國(guó)和親拖刃。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 迭代器 (iterator) 是 C++ 程序中常用的一種設(shè)計(jì)模式贪绘,它最重要的作用是為訪問(wèn)容器提供了統(tǒng)一的接口。 ...
    番茄吐司君閱讀 13,506評(píng)論 3 9
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,523評(píng)論 1 51
  • 2. C++標(biāo)準(zhǔn)庫(kù) 2.1 IO庫(kù) IO對(duì)象無(wú)拷貝或賦值央碟,進(jìn)行IO操作的函數(shù)通常以引用方式傳遞和返回流税灌。 IO庫(kù)條...
    王偵閱讀 1,337評(píng)論 0 0
  • 迭代器 1972年,麻省理工學(xué)院的Barbara Liskov和一組科學(xué)家開(kāi)始研究新的編程方法亿虽,他們將重點(diǎn)放在對(duì)用...
    JunChow520閱讀 2,071評(píng)論 0 1
  • 這周的課講了將泛型算法×獾樱現(xiàn)在將泛型算法收集下,備用洛勉。 (1)泛型算法用迭代器來(lái)解決第一個(gè)要求:遍歷容器粘秆。所有迭代器...
    shenhua8369閱讀 247評(píng)論 0 0