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

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

生活随笔

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

编程问答

[转载]《STL源码剖析》阅读笔记之 迭代器及traits编程技法

發(fā)布時(shí)間:2023/12/10 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [转载]《STL源码剖析》阅读笔记之 迭代器及traits编程技法 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?? 本文從三方面總結(jié)迭代器

  • ? 迭代器的思想
  • ? 迭代器相應(yīng)型別及traits思想
  • ? __type_traits思想
  • ?

    一 迭代器思想

    ??? 迭代器的主要思想源于迭代器模式,其定義如下:提供一種方法,使之能夠依序巡防某個(gè)聚合物(容

    器)所含的元素,而又無(wú)需暴露該聚合物的內(nèi)部表達(dá)式。可見(jiàn)她的主要作用便是能夠降低耦合,提高代碼的

    模塊性。

    ????STL的的中心思想在于:將數(shù)據(jù)容器和算法分開(kāi),彼此獨(dú)立設(shè)計(jì),最后再以一貼膠著劑將它們撮合

    在一,這貼膠著劑便是迭代器。迭代器的行為類(lèi)似智能指針(例如標(biāo)準(zhǔn)庫(kù)的auto_ptr和boost庫(kù)的shared

    _ptr),換句話說(shuō)它重載了* 和 –> 運(yùn)算符,由于設(shè)計(jì)一個(gè)適用于所有容器的迭代器是非常困難的,每個(gè)

    迭代器都必須很了解容器,所以STL的每一種容器都提供了相應(yīng)的專(zhuān)屬迭代器。

    ??? STL在廣義上有5種迭代器類(lèi)型(不限于這5種,還可以是原生指針等,具體的容器定義自己的迭代器但

    是類(lèi)型是這幾種之一或者是原生指針等)

    • ???input iterator?: 這種迭代器所指對(duì)象不允許外界改變,即是只讀的
    • ???output iterator?: 唯寫(xiě)
    • ? ?forward iterator?: 允許寫(xiě)入型算法
    • ???bidirectional iterator?: 可雙向移動(dòng)的迭代器
    • ???random access iterator?:? 涵蓋所有指針運(yùn)算能力,可隨機(jī)訪問(wèn)任何位

    ??? 它們?cè)赟TL中的定義如下:

    template <class T, class Distance> struct input_iterator {typedef input_iterator_tag iterator_category;typedef T value_type;typedef Distance difference_type;typedef T* pointer;typedef T& reference; }; struct output_iterator {typedef output_iterator_tag iterator_category;typedef void value_type;typedef void difference_type;typedef void pointer;typedef void reference; }; template <class T, class Distance> struct forward_iterator {typedef forward_iterator_tag iterator_category;typedef T value_type;typedef Distance difference_type;typedef T* pointer;typedef T& reference; }; template <class T, class Distance> struct bidirectional_iterator {typedef bidirectional_iterator_tag iterator_category;typedef T value_type;typedef Distance difference_type;typedef T* pointer;typedef T& reference; }; template <class T, class Distance> struct random_access_iterator {typedef random_access_iterator_tag iterator_category;typedef T value_type;typedef Distance difference_type;typedef T* pointer;typedef T& reference; };

    ?

    二 迭代器相應(yīng)型別及traits思想

    ??? 書(shū)中把traits技法稱(chēng)為STL源代碼的門(mén)鑰,可見(jiàn)其十分重要。先介紹迭代器相應(yīng)型別,從字面上意義來(lái)

    說(shuō)便是和迭代器相關(guān)的類(lèi)型信息,實(shí)際上有5種常用的迭代器類(lèi)型:

    • ????value type?: 迭代器所指對(duì)象的型別
    • ????difference type?: 迭代器之間的距離型別
    • ????reference type?: 迭代器引用型別
    • ????pointer type?: 迭代器指針型別
    • ????iterator_category?: 迭代器本身的型別

    ??? STL內(nèi)部需要知道當(dāng)前的迭代器的這些型別信息,其所使用的方法主要是模板的參數(shù)推導(dǎo)、模板內(nèi)嵌型

    以及模板偏特化。這里介紹下模板偏特化的概念。

    模板的偏特化是指任何template參數(shù)更進(jìn)一步的條件限制所設(shè)計(jì)出來(lái)的一個(gè)特化版本,例如

    template<typename T>

    class C{…}???? //這個(gè)版本允許T為任何類(lèi)型

    ?

    template<typename T>

    class C<T*>{…} //這個(gè)特化版本僅適用于“T為原生指針的”的情況,它比上面的更特殊

    ?????有了模板偏特化,就可以讓traits萃取出原生指針(譬如vector的迭代器就是原生指針型別的)以及指

    向常量的原生指針型別而不僅僅是類(lèi)類(lèi)型的,而負(fù)責(zé)萃取的便是?iterator_traits:

    template <class Iterator> struct iterator_traits {typedef typename Iterator::iterator_category iterator_category;typedef typename Iterator::value_type value_type;typedef typename Iterator::difference_type difference_type;typedef typename Iterator::pointer pointer;typedef typename Iterator::reference reference; };

    ??? 如果是類(lèi)類(lèi)型的性別,用上面這個(gè)就可以獲得其5個(gè)相應(yīng)型別,當(dāng)然這些型別必須都在相應(yīng)iterator類(lèi)

    面定義好(見(jiàn)第一節(jié)的5種迭代器的定義),那么如果不是上面5種而是原生指針等其他型別呢?這時(shí)候

    就用到模板偏特化:

    //原生指針用這個(gè) template <class T> struct iterator_traits<T*> {typedef random_access_iterator_tag iterator_category;typedef T value_type;typedef ptrdiff_t difference_type;typedef T* pointer;typedef T& reference; }; //指向常量的原生指針用這個(gè) template <class T> struct iterator_traits<const T*> {typedef random_access_iterator_tag iterator_category;typedef T value_type;typedef ptrdiff_t difference_type;typedef const T* pointer;typedef const T& reference; };

    ??? 通過(guò)這個(gè)traits我們就可以獲得任何一種iterator的相應(yīng)型別,通過(guò)以下表達(dá)式即可:

    ??? iterator_traits<…>::…

    ??? 說(shuō)到這里有一個(gè)很重要是設(shè)計(jì)思想不得不提,就是通過(guò)函數(shù)重載在編譯時(shí)決策正確的函數(shù)調(diào)用。這個(gè)問(wèn)

    題源于5種迭代器的類(lèi)型,它們的巡防能力是不同的,例如random acess iterator是巡防能力最強(qiáng)的,可

    O(1)時(shí)間巡防指定位置,而這個(gè)用其他的迭代器可能需要O(n)。所以為了提高效率,我們應(yīng)該用和迭代

    類(lèi)型最匹配的算法函數(shù)去調(diào)用,能用random access iterator的就不要用其他的。那么怎么做呢?

    • ??? 首先通過(guò)traits獲得iterator_category,這樣我們能夠知道當(dāng)前迭代器的類(lèi)型。實(shí)際上iterator_category就是用來(lái)提供這種服務(wù)的。
    • ??? 在函數(shù)調(diào)用時(shí)生成相應(yīng)迭代器類(lèi)型的臨時(shí)對(duì)象作為實(shí)參傳遞,編譯器就會(huì)調(diào)用相應(yīng)的重載函數(shù)。

    ??? 為了重載函數(shù)識(shí)別,我們有對(duì)應(yīng)的5種迭代器標(biāo)識(shí)類(lèi):

    struct input_iterator_tag {}; struct output_iterator_tag {}; struct forward_iterator_tag : public input_iterator_tag {}; struct bidirectional_iterator_tag : public forward_iterator_tag {}; struct random_access_iterator_tag : public bidirectional_iterator_tag {}; 繼承是為了可以使用傳遞調(diào)用,當(dāng)不存在某種迭代器類(lèi)型匹配時(shí)編譯器會(huì)依據(jù)繼承層次向上查找進(jìn)行傳遞。 以distance為例: //這里category()就是為了產(chǎn)生臨時(shí)對(duì)象 template <class InputIterator> inline iterator_traits<InputIterator>::difference_type distance(InputIterator first, InputIterator last) {typedef typename iterator_traits<InputIterator>::iterator_category category;return __distance(first, last, category()); } //input iterator 版,注意函數(shù)形參最后的類(lèi)型 template <class InputIterator> inline iterator_traits<InputIterator>::difference_type __distance(InputIterator first, InputIterator last, input_iterator_tag) {iterator_traits<InputIterator>::difference_type n = 0;while (first != last) {++first; ++n;}return n; } //random access iterator 版 template <class RandomAccessIterator> inline iterator_traits<RandomAccessIterator>::difference_type __distance(RandomAccessIterator first, RandomAccessIterator last,random_access_iterator_tag) {return last - first; }

    三?__type_traits思想

    ??? 有了前面的基礎(chǔ),我們理解到STL是非常重視效率的,而SGI STL又在其基礎(chǔ)上實(shí)現(xiàn)了一個(gè)

    __type_traits,根據(jù)前面的經(jīng)驗(yàn)我們知道它是一個(gè)萃取劑,只不過(guò)它萃取的型別是:

    • ??? 是否具備non-trivial default ctor?
    • ??? 是否具備non-trivial copy ctor?
    • ??? 是否具備non-trivial assignment operator?
    • ??? 是否具備non-trivial dtor?

    ??? 這里的non-trivial意指非默認(rèn)的相應(yīng)函數(shù),我們知道編譯器會(huì)為每個(gè)類(lèi)構(gòu)造以上四種默認(rèn)的函數(shù),如

    果沒(méi)有定義自己的,就會(huì)用編譯器默認(rèn)函數(shù),如果使用默認(rèn)的函數(shù),本來(lái)就是按位拷貝我們可以使用memcpy

    等函數(shù)來(lái)加快速度,提高效率。

    ??? 為了使用函數(shù)重載決議,我們使用類(lèi)類(lèi)型來(lái)定義兩種類(lèi)型,__true_type和__false_type

    struct __true_type { }; struct __false_type { }; template <class type> struct __type_traits { typedef __true_type this_dummy_member_must_be_first;typedef __false_type has_trivial_default_constructor;typedef __false_type has_trivial_copy_constructor;typedef __false_type has_trivial_assignment_operator;typedef __false_type has_trivial_destructor;typedef __false_type is_POD_type; }; 這個(gè)是泛化版,STL對(duì)幾乎每種內(nèi)置類(lèi)型都定義了相應(yīng)的特化版本來(lái)制定它們的類(lèi)型,整體實(shí)現(xiàn)不難。 ? 后記: 通過(guò)迭代器的設(shè)計(jì),我們能夠看到很多非常有價(jià)值的思想,也對(duì)模板的強(qiáng)大有了更加深刻的認(rèn)識(shí),這些也是 繼續(xù)閱讀STL源碼的基礎(chǔ)。

    轉(zhuǎn)載地址:http://www.cnblogs.com/HappyAngel/archive/2011/04/19/2021413.html

    轉(zhuǎn)載于:https://www.cnblogs.com/HXloveLL/p/3698533.html

    總結(jié)

    以上是生活随笔為你收集整理的[转载]《STL源码剖析》阅读笔记之 迭代器及traits编程技法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

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