迭代器是一種抽象的設(shè)計概念,《Design Patterns》一書中對于 iterator 模式的定義如下:提供一種方法,使之能夠依序巡訪某個聚合物(容器)所含的各個元素,而又無需暴露該聚合物的內(nèi)部表述方式。
創(chuàng)新互聯(lián)建站是一家專業(yè)提供項城企業(yè)網(wǎng)站建設(shè),專注與成都做網(wǎng)站、成都網(wǎng)站制作、H5場景定制、小程序制作等業(yè)務(wù)。10年已為項城眾多企業(yè)、政府機構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站設(shè)計公司優(yōu)惠進行中。為什么需要迭代器萃取有時在我們使用迭代器的時候,很可能會用到其相應(yīng)型別(associated type)。什么是相應(yīng)型別,迭代器所指之物的型別、所屬的類型(隨機迭代器、單向雙向、只讀只寫)便是。
如果我們想要以迭代器所指之物型別為類型聲明一個變量,該怎么辦呢?
一種解決方法是:利用 function template 的參數(shù)推倒(argument deducation)機制。
例如:
templatevoid func(I iter, T t) {T tmp; // 成功聲明了迭代器所指之物類型的變量
}
templatevoid func(I iter) {func_impl(iter, *iter);
}
int main() {int num = 0;
func(&num);
}
但迭代器的型別不只是迭代器所指對象的型別,而且上述解法并不能用于所有情況,因此需要更加全面的解法。
比如上述解法就無法解決 value type 用于函數(shù)返回值的情況,畢竟推導(dǎo)的只是參數(shù),無法推導(dǎo)返回值型別。
聲明內(nèi)嵌類型似乎是個很好的方法,像這樣:
templatestruct MyIter {typedef T value_type;
T* ptr;
MyIter(T* p) {ptr = p;
}
T& operator*() {return *ptr;
}
};
templatetypename I::valie_type func (I ite) {// typename I::valie_type 為返回值類型
return *ite;
}
MyIterite(new int(1231));
cout<< func(ite)<< endl;
此處 typename 的作用是告訴編譯器這是一個類型,因為 I 是一個模板參數(shù),在它被具現(xiàn)化之前編譯器對它一無所知,也就是說編譯器不知道 I::valie_type 是個類型或是成員函數(shù)等等。
更多關(guān)于 typename 的用法可以看這個鏈接:typename 的用法
還有一種情況是上述代碼無法解決的,那就是不是所有的迭代器都是 class type,原生指針就不是。如果不是 class type 就無法為它定義內(nèi)嵌型別,因此我們需要對原生指針作些特殊處理。
例如:
templatestruct iterator_traits {typedef typename I::value_type value_type;
};
templatestruct iterator_traits{typedef T value_type;
};
templatestruct iterator_traits{typedef T value_type;
};
此時,不管是 class type 類型的迭代器還是原生指針都可以處理了。
迭代器萃取,就是為我們榨取出迭代器的相應(yīng)型別。當然,要使萃取有效的運行,每個迭代器都要自行以內(nèi)嵌性別定義(nested typedef)的方式定義出相應(yīng)型別。
最常用的迭代器型別有五種:value type,difference type,pointer,reference,iterator catagoly。
迭代萃取機 traits 會很忠實地將它們榨取出來:
templatestruct iterator_traits {typedef typename I::iterator_category iterator_category;
typedef typename I::value_type value_ type;
typedef typename I::difference_type difference_type;
typedef typename I::pointer pointer;
typedef typename I::reference reference;
};
iterator_traits 必須針對傳入型別為 point 及 point-to-const 者,設(shè)計特化版本。
value typevalue type 是指迭代器所指對象的型別。
做法如上文所述。
difference typedifference type 用來表示兩個迭代器之間的距離。對于連續(xù)空間的容器來說,頭尾之間的距離就是大容量,因此它也可以用來表示一個容器的大容量。
如果一個泛型算法提供記數(shù)功能,例如 STL 的count()
,其返回值就必須使用迭代器的 difference type:
templatetypename iterator_traits::difference_type // 返回值類型,實際是 I::difference type
count(I first, I last, const T& value) {typename iterator_traits::difference_type ret = 0;
for (; first != last; ++first) {if (*first == value) {ret++;
}
}
return ret;
}
針對相應(yīng)型別 difference type,traits 的兩個特化版本,以 C++ 內(nèi)建的 ptrdiff_t 作為原生指針的 difference type。
templatestruct iterator_traits {typedef typename I::difference_type difference_type;
};
templatestruct iterator_traits{typedef ptrdiff_t difference_type;
};
templatestruct iterator_traits{typedef ptrdiff_t difference_type;
};
reference type從迭代器所指之物的內(nèi)容是否允許改變的角度來說,迭代器分為兩種:不允許改變所指對象的內(nèi)容者,稱為 constant iterators;允許改變所指對象的內(nèi)容者,稱為 mutable iterators。當我們對允許改變內(nèi)容的迭代器進行解引用操作時,獲得的不應(yīng)是一個右值,應(yīng)該是一個左值,因為右值不允許賦值操作。
在 C++ 中,函數(shù)如果要傳回左值,都是以引用的方式進行。所以當 p 是個 mutable iterators 時,如果其 value type 是 T,那么 *p 的型別不應(yīng)該是 T,而應(yīng)是 T&。同樣的,如果 p 是一個 constant iterators,其 value type 是 T,那么 *p 的型別不應(yīng)該是 const T,而應(yīng)該是 const T&。實現(xiàn)將在下一部分給出。
point type同樣的問題也出現(xiàn)在指針這里,能否改變所指地址的內(nèi)容,影響著取出的指針類型。
實現(xiàn)如下:
templatestruct iterator_traits {typedef typename I::pointer pointer;
typedef typename I::reference reference;
};
templatestruct iterstor_traits{typedef T* pointer;
typedef T& reference;
};
templatestruct iterstor_traits{typedef const T* pointer;
typedef const T& reference;
};
iterator_category根據(jù)移動特性與施行操作,迭代器被分為五類:
前三種支持operator++
,第四種再加上oprerator--
,最后一種則涵蓋所有指針算術(shù)能力。
這些迭代器的分類與從屬關(guān)系,可以用下圖表示。直線與箭頭并非表示繼承關(guān)系,而是所謂概念與強化的關(guān)系。更類似于,隨機迭代器是一個雙向迭代器,雙向迭代器也是一個單向迭代器的概念。
設(shè)計一個算法時,要盡可能針對圖中某種迭代器提供一個明確定義,并針對更加強化的某種迭代器提供另一種定義,這樣才能在不同情況下提供大效率。
以 distance() 為例distance()
函數(shù)用來計算兩個迭代器之間的距離。針對不同的迭代器類型,它可以用不同的計算方式,帶來不同的效率。
templateinline iterator_traits::difference_type
__distance(InputIterator first, InputIterator last,
input_iterator_tag) {iterator_traits::iteratordifference_type n = 0;
// 逐一累計距離
while (first != last) {++first;
++n;
}
return n;
}
templateinline iterator_traits::difference_type
__distance(RandomAccessIterator first, RandomAccessIterator last,
random_access_iterator_tag) {// 直接計算差距
return last - first;
}
// InputIterator 命名規(guī)則:所能接受的最低階迭代器類型
templateinline iterator_traits::difference_type
distance(InputIterator first, InputIterator last) {typedef typename iterator_traits::iterator_category category;
return __distance(first, last, category());
}
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
本文名稱:STL迭代器萃取-創(chuàng)新互聯(lián)
文章URL:http://m.rwnh.cn/article30/cciepo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名、網(wǎng)站導(dǎo)航、靜態(tài)網(wǎng)站、網(wǎng)站策劃、網(wǎng)站維護、網(wǎng)頁設(shè)計公司
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容