<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    weidagang2046的專欄

    物格而后知致
    隨筆 - 8, 文章 - 409, 評論 - 101, 引用 - 0
    數據加載中……

    學STL Iterator,traits筆記

    最近看侯杰老師的《STL源碼剖析》有一點收獲,特把我對STL iterator設計的認識草草記錄下來,大部分內容來自那本書(看原書更好)。歡迎大家跟我討論,里面也有問題希望您能提供寶貴看法!

    一. Iterator認識
    如果需要構造一組通用容器,提供一套統一的算法,構造底層數據結構類庫,iterator的設計無疑是非常重要的。iterator可以方便容器元素的遍歷,提供算法的統一參數接口。怎么說?首先,讓我們考慮一個算法。
    Template <class T> ptrdiff_t
    distance(T p1, T p2)
    {
    ? //計算p1和p2之間的距離
    }

    顯然這個函數是想計算兩個“位置”之間距離。這里表示“位置”的類型T,可以是指向數組中某個元素的(原生)指針,可以是指向鏈表節點的指針,也可以是用來記錄位置的任何對象(例如我們要談的iterator)。不管這兩個位置是對應在數組,vector,鏈表或是其他任何容器,我們當然希望設計好的類庫中最好只要一個這樣的distance函數,而不需要每種容器都有不同的“位置”記錄方式,從而導致需要很多個這樣的distance算法。對,我們完全可以抽象出一種表示“位置”的概念,它像游標,像智能的指針,可以方便的遍歷容器中的元素,記錄位置,而不用管你作用的是什么類型的容器,這就是現在被容器設計者普遍接受的iterator概念。




    二. STL iterator的設計:
    為什么不用繼承構造iterator?
    容器抽象出5種iterator 類型,input<--forward<--bidrectional<--random access iterator加上output iterator,我們能不能通過refinement關系設計出具有繼承關系的幾個iterator類?然后各個容器的iterator類去繼承這些基類。那么上面的disatance函數可以設計兩個版本
    ptrdiff_t distance(InputIterator p1, InputIterator p2)
    {
    ?//InputIterator只能一個一個前進,例如鏈表
    ? ptrdiff_t n=0;
    ? while(p1 != p2)
    ? {
    ? ?++p1; ++n;? ?
    ? }
    ? return n;
    }

    ptrdiff_t distance(RandomAccessIterator p1, RandomAccessIterator p2)
    {
    ?//RandomAccessIterator可以直接計算差距,例如數組,vector等
    ?return p2-p1;
    }

    這樣看來是可行的對嗎?但為什么STL不采用這種方式呢?(各位幫我想想啊,我實在是菜,想不出很好的理由啊)我所能想到的有:iterator可以是原生指針的類型,而原生指針是不會繼承InputIterator基類的。(是不是還有效率問題?)

    不討論STL為什么不這么作,還是看看它漂亮的處理方法吧:先提醒你,它用的是函數模板(function template)的參數推導機制來確定函數返回值和參數類型的。

    (1)? 通過不同的iterator概念,先作幾個表明iterator類型的tag類。input_iterator_tag<--forward_iterator_tag<--bidrectonal_iterator_tag<--random_access_iterator_tag。還有output_iterator_tag,這幾個類都是空的,前面4個有繼承關系。

    (2)? STL設計的iterator類都需要typedef一個重要的類型iterator_category用來表明這個iterator是什么類型的iterator,它必須是上面tag類中的一個。例如list<T>的iterator類有:
    ??? typedef bidrectonal_iterator_tag iterator_category;
    ???
    ??? 另外需要有一個value_type類型表明iterator是指向什么類型的元素。例如list<T>的iterator類有:
    ??? typedef T value_type;

    (3)? 設計iterator_traits<class Iterator>類,這個類的作用是可以提取出模板參數Iterator類的類型。也是通過typedef實現的。如下:
    template <class Iterator>
    struct iterator_traits {
    ? typedef typename Iterator::iterator_category iterator_category;
    ? typedef typename Iterator::value_type??????? value_type;
    ? //.....
    };

    本來第二步中,我們設計的iterator類已經可以通過typedef別名來標志類型了,為什么要這層中間轉換?原因是通常我們可以寫Iterator::iterator_category作為一個typename,但如果Iterator是一個原生指針T*,我們寫T*::iterator_category就得不到啦。利用partial specialization(模板偏特化)技術,可以通過中間層iterator_traits自己指定并得到原生指針的iterator_category類型,代碼如下。(這么復雜的編譯技術,真不知他們咋整的...吾輩只能望洋興嘆55)

    template <class T>
    struct iterator_traits<T*> {
    ? typedef random_access_iterator_tag iterator_category;
    ? typedef T????????????????????????? value_type;
    ? //........
    };

    (4)? 設想要設計一個算法template <class Iterator> RET_TYPE gen_fun(Iterator p1, Iterator p2, ...)。
    一般這么處理:
    template <class Iterator> RET_TYPE gen_fun(Iterator p1, Iterator p2, ...)
    {
    ??? typedef iterator_traits<Iterator>::iterator_category category;???
    ??? typedef iterator_traits<Iterator>::value_type type;? //這個type用于實際運算中得知iterator指向的對象(*運算符返回類型)
    ?? __gen_fun(Iterator p1, Iterator p2, ..., category());
    }

    category()構造一個iterator_tag類型的臨時變量,該臨時變量只用于區分調用函數,不參與實際算法實現。具體實現方法如下:(注意最后的參數不用變量名)

    template <class Iterator> RET_TYPE __gen_fun(Iterator p1, Iterator p2, ..., input_iterator_tag)
    {
    ?? //input_iterator類型的實際實現方法
    ?? //并且由于tag類繼承機制,forward_iterator類型也會調用本方法
    }

    ?
    template <class Iterator> RET_TYPE __gen_fun(Iterator p1, Iterator p2, ..., bidrectonal_iterator_tag)
    {
    ?? //bidrectonal_iterator類型的實際實現方法
    }

    template <class Iterator> RET_TYPE __gen_fun(Iterator p1, Iterator p2, ..., random_access_iterator_tag)
    {
    ?? //random_access_iterator類型的實際實現方法
    }

    這樣通過定義iterator tag和函數模板的參數推導機制,就實現了參數類型識別,達到了構造繼承關系的iterator類實現的功能。并且沒有繼承要求那么嚴格,而且typedef是在編譯時候完成的工作,絲毫不影響程序運行速度。如果增加iterator中typedef的類型,如pointer等,可以增強參數類型識別的功能。

    另外需要提醒的是,在STL代碼中,如果是random_access_iterator類型的方法,它通常寫
    template <class RandomAccessIterator> RET_TYPE __gen_fun(RandomAccessIterator p1, RandomAccessIterator p2, ..., random_access_iterator_tag)
    是input_iterator類型的方法,它通常寫
    template <class InputIterator> RET_TYPE __gen_fun(InputIterator p1, InputIterator p2, ..., input_iterator_tag)
    但是,別被這里的RandomAccessIterator和InputIterator迷惑了,它們只是模板參數而已,并沒有繼承關系,也不存在這樣的類!(我就被這個迷惑了好久:( )也不是我開頭提的構造一組繼承關系的Iterator類。模板參數寫成RandomAccessIterator并不能表示該RandomAccessIterator類型就是random_access_iterator的,它寫成T,Type,Iter都沒有關系。只有通過iterator_traits得到iterator_tag才能表明iterator的真正類型。我想它那樣寫,只是為了提醒你調用函數的iterator類型吧。



    三. 最后看看開頭提的distance()算法實際實現

    template <class Iterator> inline
    ?typename iterator_traits<Iterator>::iterator_category
    ? iterator_category(const Iterator&)?
    ? //提取Iterator的iterator_category類型
    {
    ? typedef typename iterator_traits<Iterator>::iterator_category category;
    ? return category();
    }


    template <class InputIterator, class Distance>
    inline void distance(InputIterator first, InputIterator last, Distance& n)?
    {
    ? __distance(first, last, n, iterator_category(first));
    ? //根據提取的iterator_category類型選擇實際執行函數
    ? //Distance是通過引用傳遞,相當于函數返回值
    }


    template <class InputIterator, class Distance>
    inline void __distance(InputIterator first, InputIterator last, Distance& n,
    ?????????????????????? input_iterator_tag)
    {
    ? //input_iterator類型的實現,根據input_iterator_tag的繼承關系,forward_iterator
    ??//和bidrectonal_iterator也會調用此實現函數。
    ? while (first != last) { ++first; ++n; }
    }

    template <class RandomAccessIterator, class Distance>
    inline void __distance(RandomAccessIterator first, RandomAccessIterator last,
    ?????????????????????? Distance& n, random_access_iterator_tag)
    {
    ? //random_access_iterator類型的實現
    ? n += last - first;
    }

    ????????????????????????????????????????????????????????????????????????????? 2004.11.10
    from: http://www.zahui.com/html/9/35875.htm

    posted on 2006-09-25 11:48 weidagang2046 閱讀(3774) 評論(0)  編輯  收藏 所屬分類: C/C++

    主站蜘蛛池模板: 亚洲日韩看片无码电影| 美女被免费视频网站| 免费看大美女大黄大色| 91av免费在线视频| 亚洲国产成人精品电影| 亚洲高清无码专区视频| 五月亭亭免费高清在线| 无套内射无矿码免费看黄| 日本久久久久亚洲中字幕| 日韩免费观看一级毛片看看| 亚欧国产一级在线免费| 亚洲永久在线观看| 亚洲国产精品SSS在线观看AV| 国产精品无码免费播放| 久久久久免费精品国产 | 久久久久久久99精品免费| 中文字幕乱码亚洲精品一区| 亚洲精品无码不卡在线播HE| 免费看片免费播放| 日韩精品内射视频免费观看| 免费一级做a爰片久久毛片潮| 亚洲国产成AV人天堂无码| 亚洲中文字幕无码永久在线 | 免费无码一区二区三区蜜桃大| 国产免费阿v精品视频网址| 亚洲一区二区三区丝袜| 亚洲情a成黄在线观看动漫尤物| 亚洲AV之男人的天堂| 国产成在线观看免费视频| 99久久国产精品免费一区二区| 免费观看亚洲人成网站| 中文字幕在线免费观看视频| 亚洲人成77777在线播放网站不卡 亚洲人成77777在线观看网 | 国产免费阿v精品视频网址| 国产天堂亚洲国产碰碰| 亚洲深深色噜噜狠狠网站| 97亚洲熟妇自偷自拍另类图片| 亚洲熟妇av一区二区三区| 亚洲精品NV久久久久久久久久| 免费无遮挡无码视频网站| 男人的好看免费观看在线视频|