<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 閱讀(3775) 評論(0)  編輯  收藏 所屬分類: C/C++

    主站蜘蛛池模板: 久久亚洲色WWW成人欧美| 中文字幕乱码亚洲精品一区| www成人免费视频| 免费萌白酱国产一区二区| 亚洲精品又粗又大又爽A片| 青苹果乐园免费高清在线| 在线观看亚洲AV每日更新无码| 国产精品无码免费播放| 亚洲日本在线电影| 国产精品国产午夜免费福利看| 亚洲成a人无码亚洲成av无码| 日韩a级毛片免费视频| 在线观看亚洲专区| 亚洲精品动漫人成3d在线| h视频在线观看免费| 亚洲av无码乱码国产精品| 香港a毛片免费观看| 亚洲国产av高清无码| 成人性生活免费视频| 亚洲av成人一区二区三区观看在线 | 91嫩草亚洲精品| 成年午夜视频免费观看视频| 国产精品亚洲精品日韩动图 | 免费无码又爽又刺激高潮| 亚洲欧美成人一区二区三区| 亚洲Av无码乱码在线znlu| 久久久WWW免费人成精品| 亚洲资源在线观看| 国外成人免费高清激情视频| 日本一区二区三区在线视频观看免费 | 国内精品免费视频自在线| 日韩亚洲人成在线综合| 亚洲自偷自偷图片| 亚洲成人免费在线观看| 国产精品亚洲专一区二区三区| 中文亚洲成a人片在线观看| 亚洲免费电影网站| 特a级免费高清黄色片| 久久精品国产亚洲77777| 国产a不卡片精品免费观看| 国产va在线观看免费|