淺談C++反向迭代器的設(shè)計(jì)
前言
STL中不少的容器需要有迭代器這樣的設(shè)計(jì),特別是正向迭代器,幾乎每個(gè)容器都有自己的特定實(shí)現(xiàn)方式,有了正向迭代器之后,我們還要提供反向迭代器以供一些特殊的需求,但是許多容器的正向迭代器實(shí)現(xiàn)的方式不一樣,如果我們要實(shí)現(xiàn)其反向迭代器,每個(gè)容器的反向迭代器的實(shí)現(xiàn)方式也不一樣,有沒有一種方法能夠統(tǒng)一反向迭代器的實(shí)現(xiàn)方式呢?
有的,那就是拿已有的正向迭代器進(jìn)行封裝,這樣只要我們實(shí)現(xiàn)了正向迭代器,反向迭代器自然而然就形成了,本篇文章我們就來一起探究這種設(shè)計(jì)方式。
一、反向迭代器的結(jié)構(gòu)
我們設(shè)計(jì)的反向迭代器是用正向迭代器實(shí)現(xiàn)的,這樣反向迭代器的實(shí)現(xiàn)方式就統(tǒng)一了,那么我們反向迭代器的成員變量就是一個(gè)正向迭代器,關(guān)于成員函數(shù),我們反向迭代器提供的接口與正向迭代器提供的接口一樣。
//第一個(gè)模板參數(shù)傳遞 正向迭代器,第二個(gè)傳遞 迭代器的引用 第三個(gè)傳遞 迭代器的地址 ?template<class Iterator, class Ref, class Ptr> ?//用struct定義類,因?yàn)槲覀兿胍_我們的接口 ?struct _reverse_iterator ?{ ??? ?//對自己進(jìn)行typedef方便使用 ??? ?typedef _reverse_iterator<Iterator, Ref, Ptr> self; ? ? //成員變量 是一個(gè)正向迭代器 ? ? Iterator _current; ? ? //構(gòu)造函數(shù) ? 用一個(gè)正向迭代器進(jìn)行初始化反向迭代器對象 ? ? _reverse_iterator(Iterator it) ? ? ? ? :_current(it) ? ? {} ? ? //*運(yùn)算符重載 ? ? Ref operator*(); ? ? //前置++運(yùn)算符重載 ? ? self& operator++(); ? ? //后置++運(yùn)算符重載 ? ? self operator++(int) ? ? //前置--運(yùn)算符重載 ? ? self& operator--() ? ? //后置--運(yùn)算符 ? ? self operator--(int) ? ? //->操作符 ? ? Ptr operator->() ? ? //關(guān)系運(yùn)算符 ? ? bool operator!=(const self& s); ? ? bool operator==(const self& s); ?}
容器類內(nèi)的rbegin與rend 函數(shù)
//類內(nèi)使用反向迭代器 class myclass { ? ? ?//此類內(nèi)要配套有一個(gè)正向迭代器iterator,然后傳給外面的反向迭代器 ? ? ?//將反向迭代器進(jìn)行typedef方便使用 ? ? ?typedef _reverse_iterator<iterator, T&, T*> reverse_iterator; ? ? ? //反向迭代器 ? ? ?typedef _reverse_iterator<iterator, const T&, const T*> const_reverse_iterator; ? ? ?//反向迭代器 ? ? ?reverse_iterator rbegin() ? ? ?{ ? ? ?? ?return reverse_iterator(end()); ? ? ?} ? ? ?reverse_iterator rend() ? ? ?{ ? ? ??? ?return reverse_iterator(begin()); ? ? ?} ? ? ?//const反向迭代器 ? ? ?const_reverse_iterator rbegin() const ? ? ?{ ? ? ??? ?return const_reverse_iterator(end()); ? ? ?} ? ? ?const_reverse_iterator rend() const ? ? ?{ ? ? ?? ?return const_reverse_iterator(begin()); ? ? ?} };
注意: 反向迭代器這里我們采用了對稱結(jié)構(gòu)便于理解對比,但這也導(dǎo)致我們后面在進(jìn)行*解引用操作符時(shí)要解引用前一個(gè)位置!
二、反向迭代器的接口實(shí)現(xiàn)
1、*運(yùn)算符重載
我們可以創(chuàng)建一個(gè)局部對象,對局部對象進(jìn)行--找到前一個(gè)位置,然后再進(jìn)行解引用返回就行了。
//*運(yùn)算符重載 Ref operator*() { //這里是不用寫拷貝構(gòu)造的,默認(rèn)的拷貝構(gòu)造會(huì)對內(nèi)置類型進(jìn)行值拷貝,對自定義類型調(diào)用它的拷貝構(gòu)造 Iterator tmp = _current; --tmp; return *tmp; }
2、算術(shù)運(yùn)算符 ++ - -的重載
由于我們的反向迭代器是由正向迭代器實(shí)現(xiàn)的,反向迭代器++就相當(dāng)于正向迭代器- - ,明白了這個(gè)就很好實(shí)現(xiàn)算術(shù)運(yùn)算符重載了。
//前置++運(yùn)算符重載 self& operator++() { --_current; return(*this); } //后置++運(yùn)算符重載 self operator++(int) { //保存當(dāng)前對象 self tmp(*this); --_current; //返回--之前的對象 return tmp; } //前置--運(yùn)算符重載 self& operator--() { ++_current; return (*this); } //后置--運(yùn)算符 self operator--(int) { self tmp(*this); ++_current; return tmp; }
3、->操作符重載
->運(yùn)算符重載我們只需要返回容器中存儲的自定義類型的對象的地址就行了,我們可以先調(diào)用operator*()拿到容器中存儲的對象,然后再進(jìn)行取地址&
Ptr operator->() { return &(operator*()); }
4、關(guān)系運(yùn)算符
要判斷兩個(gè)反向迭代器相不相等,只需要判斷反向迭代器里面的成員變量相不相等就行了。
//關(guān)系運(yùn)算符 bool operator!=(const self& s) { return _current != s._current; } bool operator==(const self& s) { return _current == s._current; }
到這里我們的反向迭代器就已經(jīng)形成了。
三、關(guān)于反向迭代器的一些討論
由于我們的反向迭代器是用模板寫的,當(dāng)我們將vector的迭代器類型傳遞過去時(shí),我們的反向迭代器就變成了vector的反向迭代器,當(dāng)我們將list的迭代器傳遞過去時(shí),就形成了list的反向迭代器。
傳遞的迭代器必須的二元迭代器,可以++ ,- -。forward_list的迭代器就不行!
例如:實(shí)現(xiàn)vector的反向迭代器,我們只需要在類內(nèi)部傳遞一下正向迭代器,然后typedef一下就行了。
template<class T> class vector { public: ?? ?//正向迭代器 ?? ?typedef ?T* iterator; ?? ?//反向迭代器 ? 將正向迭代器進(jìn)行傳遞給反向迭代器 ?? ?typedef _reverse_iterator<iterator, T&, T*> reverse_iterator; ?? ?typedef _reverse_iterator<iterator, const T&, const T*> const_reverse_iterator; ?? ?//普通迭代器 ?------------------------------------------------ ?? ?iterator begin(); ?? ?iterator end(); ?? ?//const迭代器 ?? ?typedef const T* const_iterator; ?? ?const_iterator begin() const; ?? ?const_iterator end() const; ?? ?//反向迭代器 ?? ?reverse_iterator rbegin() ?? ?{ ?? ??? ?return reverse_iterator(end()); ?? ?} ?? ?reverse_iterator rend() ?? ?{ ?? ??? ?return reverse_iterator(begin()); ?? ?} ?? ?//const反向迭代器 ?? ?const_reverse_iterator rbegin() const ?? ?{ ?? ??? ?return const_reverse_iterator(end()); ?? ?} ?? ?const_reverse_iterator rend() const ?? ?{ ?? ??? ?return const_reverse_iterator(begin()); ?? ?} ?? ?......? ?? ?......? ?? ?......? };
到此這篇關(guān)于淺談C++反向迭代器的設(shè)計(jì)的文章就介紹到這了,更多相關(guān)C++反向迭代器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言數(shù)據(jù)結(jié)構(gòu)之堆排序詳解
堆是計(jì)算機(jī)科學(xué)中一類特殊的數(shù)據(jù)結(jié)構(gòu)的統(tǒng)稱,通常是一個(gè)可以被看做一棵完全二叉樹的數(shù)組對象。而堆排序是利用堆這種數(shù)據(jù)結(jié)構(gòu)所設(shè)計(jì)的一種排序算法。本文將通過圖片詳細(xì)介紹堆排序,需要的可以參考一下2022-03-03用C語言實(shí)現(xiàn)從文本文件中讀取數(shù)據(jù)后進(jìn)行排序的功能
這是一個(gè)十分可靠的程序,這個(gè)程序的查錯(cuò)能力非常強(qiáng)悍。程序包含了文件操作,歸并排序和字符串輸入等多種技術(shù)。對大家學(xué)習(xí)C語言很有幫助,有需要的一起來看看。2016-08-08C++實(shí)現(xiàn)LeetCode(309.買股票的最佳時(shí)間含冷凍期)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(309.買股票的最佳時(shí)間含冷凍期),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08C語言安全編碼之?dāng)?shù)值中的sizeof操作符
這篇文章主要介紹了C語言安全編碼的數(shù)值中的sizeof操作符用法注意事項(xiàng),需要的朋友可以參考下2014-07-07C++智能指針shared_ptr與weak_ptr的實(shí)現(xiàn)分析
shared_ptr是一個(gè)標(biāo)準(zhǔn)的共享所有權(quán)的智能指針,允許多個(gè)指針指向同一個(gè)對象,定義在 memory 文件中,命名空間為 std,這篇文章主要介紹了C++ 中 shared_ptr weak_ptr,需要的朋友可以參考下2022-09-09C++數(shù)據(jù)結(jié)構(gòu)之list詳解
list是一種序列式容器。list容器完成的功能實(shí)際上和數(shù)據(jù)結(jié)構(gòu)中的雙向鏈表是極其相似的,list中的數(shù)據(jù)元素是通過鏈表指針串連成邏輯意義上的線性表,也就是list也具有鏈表的主要優(yōu)點(diǎn),即:在鏈表的任一位置進(jìn)行元素的插入、刪除操作都是快速的2021-11-11