日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

STL泛型编程之迭代器

發(fā)布時(shí)間:2024/2/28 编程问答 43 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STL泛型编程之迭代器 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

學(xué)習(xí)《C++ Primer Plus》中泛型編程的一些概念,感覺(jué)需要對(duì)這部分的知識(shí)理解的深一點(diǎn)(都是書(shū)上的內(nèi)容,只不過(guò)經(jīng)常搞不清,所以就抄了個(gè)筆記)。STL提供了一組表示容器、迭代器、函數(shù)對(duì)象和算法的模板。容器是一個(gè)與數(shù)組類(lèi)似的單元,可以存儲(chǔ)若干個(gè)值。STL容器是同質(zhì)的,即存儲(chǔ)的值的類(lèi)型相同;算法是完成特定任務(wù)的“處方”;迭代器能夠用來(lái)遍歷容器的對(duì)象,與能夠遍歷數(shù)組的指針類(lèi)似,是廣義指針;函數(shù)對(duì)象是類(lèi)似于函數(shù)的對(duì)象,可以是類(lèi)對(duì)象或函數(shù)指針(包括函數(shù)名,因?yàn)楹瘮?shù)名被用作指針)。

?

泛型編程

面向?qū)ο缶幊剃P(guān)注的是編程的數(shù)據(jù)方面,而泛型編程關(guān)注的是算法。它們之間的共同點(diǎn)是抽象和創(chuàng)建可重用代碼,但它們的理念絕然不同。

泛型編程旨在編寫(xiě)?yīng)毩⒂跀?shù)據(jù)類(lèi)型的代碼。在C++中,完成通用程序的工具是模板。當(dāng)然,模板使得能夠按泛型定義函數(shù)或類(lèi),而STL通過(guò)通用算法更進(jìn)一步。模板讓這一切成為可能,但必須對(duì)元素進(jìn)行仔細(xì)地設(shè)計(jì)。為解模板和設(shè)計(jì)師如何協(xié)同工作的,來(lái)看一看需要迭代器的原因。

理解迭代器是理解STL的關(guān)鍵所在。模板使得算法獨(dú)立于存儲(chǔ)的數(shù)據(jù)類(lèi)型,而迭代器使算法獨(dú)立于使用的容器類(lèi)型。因此,它們都是STL通用方法的重要組成部分。

為了理解為何需要迭代器,我們來(lái)看如何為兩種不同數(shù)據(jù)表示實(shí)現(xiàn)find函數(shù),然后看如何推廣這種方法。首先看一個(gè)在double數(shù)組中搜索特定值的函數(shù),可以這樣編寫(xiě)該函數(shù):

double* find_ar(double *ar, int n, const double &val) {for(int i = 0; i < n; i++){if(ar[i] == val)return &ar[i];}return 0; }

如果函數(shù)在數(shù)組中找到這樣的值,則返回該值在數(shù)組中的位地址,否則返回一個(gè)空指針。該函數(shù)使用下標(biāo)來(lái)遍歷數(shù)組。可以用模板將這種算法推廣到包含==運(yùn)算符、任意類(lèi)型的數(shù)組。盡管如此,這種算法仍然與一種特定的數(shù)據(jù)結(jié)構(gòu)(數(shù)組)關(guān)聯(lián)在一起。

?

下面來(lái)看搜索鏈表的情況。鏈表有鏈接在一起的Node結(jié)構(gòu)組成:

struct Node {double item;Node *p_next; };

假設(shè)有一個(gè)指向鏈表第一個(gè)節(jié)點(diǎn)的指針,每個(gè)節(jié)點(diǎn)的p_next指針都指向下一個(gè)節(jié)點(diǎn),鏈表最后一個(gè)節(jié)點(diǎn)的p_next指針被設(shè)置為0,則可以這樣編寫(xiě)find_ll()函數(shù):

Node* find_ll(Node *head, const double &val) {Node *start;for(start = head; start != 0; start = start->p_next){if(start->item == val)return start;}return 0; }

同樣,也可以使用模板將這種算法推廣到支持==運(yùn)算符的任何數(shù)據(jù)類(lèi)型的鏈表。然而,這種算法也是與特定的數(shù)據(jù)結(jié)構(gòu)(鏈表)相關(guān)聯(lián)在一起。

從實(shí)現(xiàn)的細(xì)節(jié)上看,這兩個(gè)find函數(shù)的算法時(shí)不同的:一個(gè)使用數(shù)組索引來(lái)遍歷元素,另一個(gè)則將start重置為start->p_next。但從廣義上講,這兩種算法是相同的:將值依次與容器中的每個(gè)值進(jìn)行比較,直到找到匹配的為止。

?

泛型編程旨在使用同一個(gè)find函數(shù)來(lái)處理數(shù)組、鏈表或任何其他的容器。即函數(shù)不僅獨(dú)立于容器中存儲(chǔ)的數(shù)據(jù)類(lèi)型,而且獨(dú)立于容器本身的數(shù)據(jù)結(jié)構(gòu)。模板提供了存儲(chǔ)在容器中的數(shù)據(jù)類(lèi)型的通用表示,因此還需要遍歷容器中的值的通用表示,迭代器正是這樣的通用表示。

要實(shí)現(xiàn)find函數(shù),迭代器應(yīng)具備的特征如下:

(1)應(yīng)能夠?qū)Φ鲌?zhí)行解除引用的操作,以便能訪問(wèn)它引用的值。即如果p是一個(gè)迭代器,則應(yīng)該對(duì)*p進(jìn)行定義。

(2)應(yīng)能夠?qū)⒁粋€(gè)迭代器賦給另一個(gè)。即如果p和q都是迭代器,則應(yīng)對(duì)表達(dá)式p = q進(jìn)行定義。

(3)應(yīng)能夠?qū)⒁粋€(gè)迭代器與另一個(gè)進(jìn)行比較,看它們是否相等。即如果p和q都是迭代器,則應(yīng)該對(duì)p == q和p != q進(jìn)行定義。

(4)應(yīng)能夠使用迭代器遍歷容器中的所有元素,這可以通過(guò)為迭代器p定義++p和p++來(lái)實(shí)現(xiàn)。

迭代器也可以完成其他的操作,但有上述功能就足夠了,至少對(duì)于find函數(shù)是如此。實(shí)際上,STL按功能的強(qiáng)弱定義了多種級(jí)別的迭代器。

?

順便說(shuō)一句,常規(guī)指針就能滿足迭代器的要求,因此,可以這樣重新編寫(xiě)find_arr()函數(shù):

typedef double *iterator; iterator find_ar(iterator ar, int n, const double &val) {for(int i = 0; i < n; i++, ar++){if(*ar == val)return ar;}return 0; }

然后可以修改函數(shù)參數(shù),使之接受兩個(gè)指示區(qū)間的指針參數(shù),其中的一個(gè)指向數(shù)組的起始位置,另一個(gè)指向數(shù)組的超尾;同時(shí)函數(shù)可以通過(guò)返回尾指針,來(lái)指出沒(méi)有找到要找的值。下面的find_arr()版本完成了這些修改:

typedef double *iterator; iterator find_ar(iterator begin, iterator end, const double &val) {iterator ar;for(ar =begin; ar != end; i++, ar++){if(*ar == val)return ar;}return end; }

對(duì)于find_ll()函數(shù),可以定義一個(gè)迭代器類(lèi),其中定義了運(yùn)算符*和++:

struct Node {double item;Node *p_next; };class iterator {Node *pt; public:iterator():pt(0) {}iterator(Node *pn):pt(pn) {}double operator*() {return pt->item;}iterator &operator++(){pt = pt->p_next;return *this;}iterator operator++(int){iterator tmp = *this;pt = pt->p_next;return tmp;} };

這里重點(diǎn)不是如何定義iterator類(lèi),而是有了這樣的類(lèi)后,第二個(gè)find函數(shù)就可以這樣編寫(xiě):

iterator find_ll(iterator head, const double &val) {iterator start;for(start = head; start != 0; ++start){if(*start == val)return start;}return 0; }

這和find_ar()幾乎相同,差別在于如何到達(dá)最后一個(gè)值。find_ar()函數(shù)使用超尾迭代器,而find_ll()使用存儲(chǔ)在最后一個(gè)節(jié)點(diǎn)中的空值。除了這種差別外,這兩個(gè)函數(shù)完全相同。例如,可以要求鏈表的最后一個(gè)元素后面還有一個(gè)額外的元素,即讓數(shù)組和鏈表都有超尾元素,并在迭代器達(dá)超尾位置時(shí)結(jié)束搜索。這樣,find_ar()和find_ll()監(jiān)測(cè)數(shù)據(jù)尾的方式將相同,從而成為相同的算法。注意,增加超尾元素后,對(duì)迭代器的要求變成了對(duì)容器的要求。

?

STL遵循上面介紹的方法。首先,每個(gè)容器類(lèi)(vector、llist、deque等)定義了相應(yīng)的迭代器類(lèi)型。對(duì)于其中的某個(gè)類(lèi),迭代器可能是指針;而對(duì)于另一個(gè)類(lèi),則可能是對(duì)象。不管實(shí)現(xiàn)方式如何,迭代器都將提供所需的操作,如*和++(有些類(lèi)需要的操作可能比其他類(lèi)多)。其次,每個(gè)容器類(lèi)都有一個(gè)超尾標(biāo)記,當(dāng)?shù)鬟f增到超越容器的最后一個(gè)值后,這個(gè)值將被賦給迭代器。每個(gè)容器類(lèi)都有begin()和end()方法,它們分別返回一個(gè)指向容器的第一個(gè)元素和超尾位置的迭代器。每個(gè)容器類(lèi)都使用++操作,讓迭代器從指向第一個(gè)元素逐步指向超尾位置,從而遍歷容器中的每一個(gè)元素。

使用容器類(lèi)時(shí),無(wú)需知道其迭代器是如何實(shí)現(xiàn)的,也無(wú)需知道超尾是如何實(shí)現(xiàn)的,而只需知道它有迭代器,其begin()返回一個(gè)指向第一個(gè)元素的迭代器,end()返回一個(gè)指向超尾位置的迭代器即可。例如,假設(shè)要打印vector<double>對(duì)象中的值,則可以這樣做:

vector<double>::iterator pr; for(pr = scores.begin(); pr != scores.end(); pr++) {cout << *pr <<endl; }

其中,下面的代碼行將pr的類(lèi)型聲明為vector<double>類(lèi)的迭代器:

vector<double>class: vector<double>::iterator pr;

如果要使用list<double>類(lèi)模板來(lái)存儲(chǔ)分?jǐn)?shù),則代碼如下:

list<double>::iterator pr; for(pr = scores.begin(); pr!= scores.end(); pr++) {cout << *pr <<endl; }

唯一不同的是pr的類(lèi)型。因此,STL通過(guò)為每個(gè)類(lèi)定義適當(dāng)?shù)牡?#xff0c;并以統(tǒng)一的風(fēng)格設(shè)計(jì)類(lèi),能夠?qū)?nèi)部表示絕然不同的容器,編寫(xiě)相同的代碼。使用C++11新增的自動(dòng)類(lèi)型推斷可進(jìn)一步簡(jiǎn)化:對(duì)于矢量或列表,都可使用如下代碼:

for(auto pr = scores.begin(); pr != scores.end(); pr++) {cout << *pr <<endl; }

實(shí)際上,作為一種編程風(fēng)格,最好避免直接使用迭代器,而應(yīng)盡可能使用STL函數(shù)(如for_each())來(lái)處理細(xì)節(jié)。也可以使用C++11新增的基于范圍的for循環(huán):

for(auto x : scores) cout << x << endl;

來(lái)總結(jié)一下STL方法。首先是處理容器的算法,應(yīng)盡可能用通用的術(shù)語(yǔ)來(lái)表達(dá)算法,使之獨(dú)立于數(shù)據(jù)類(lèi)型和數(shù)據(jù)類(lèi)型。為使通用算法能夠適用于具體情況,應(yīng)定義能夠滿足算法需求的迭代器,并把要求加到容器設(shè)計(jì)上。即基于算法的要求,設(shè)計(jì)基本迭代器的特征和容器特征。

總結(jié)

以上是生活随笔為你收集整理的STL泛型编程之迭代器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。