首页 > 其他 > 详细

迭代器实现

时间:2014-04-08 18:21:06      阅读:427      评论:0      收藏:0      [点我收藏+]

设计模式--迭代器iterator

我们知道STL两个主要内容就是容器(containers)和算法(algoritms),两者是分开设计的。关于各自独立的实现,c++中的class template和function template能很好的完成这个目标。而将两者胶合起来,则需要iterator的帮助。这就使得iterator成了STL设计中重要的一环。

迭代器是一种抽象的设计概念,《设计模式》中提供的23种设计模式中的一种。以下是对于其适用性的描述:

1.访问一个聚合对象的内容而无需暴露它的内部表示
2.支持对聚合对象的多种遍历
3.为遍历不同的聚合结构提供一个统一接口

根据《设计模式》中的观点,创建迭代器的参与者可以包含以下几个:

  • Iterator(迭代器)

    迭代器定义和访问的接口

  • ConcreteIterator(具体迭代器)

    具体实现迭代器接口,不同的类有不同的迭代实现 跟踪遍历位置

  • Aggregate(聚类)

    定义和创建相应迭代器对象的接口

  • ConcreteAggregate(具体聚类)

    具体聚合实现创建相应迭代器的接口

所以创建iterator又是一种Factor Method模式,这样做就实现了聚类与迭代机制的分离。当然,STL中的iterator并不完全按这个分层的机制实现。但是,总体上按这个模式来的,对所有的iterator有一个统一的抽象,其中定义了基本的内部类型,和基本的通用的函数操作,而对不同的容器,实现专属迭代器。

迭代器的分类

迭代器作为访问容器的一个工具,根据访问权限和移动特性可已将其分为以下几类:

  • Input iterator

    单向(operator ++),只读对象,不允许外界改变

  • Output iterator

    单向(operator ++),只写

  • Forward iterator

    单向(operator ++),能写能读

  • Bidirectional iterator

    双向(operator ++/--),能写能读

  • Random Access iterator

    双向(operator ++/--),能写能读,支持随机访问(operator +/- n)

之所以要区别这几种迭代器因为不同的迭代器,某些操作的执行效率会不一样。

迭代器的基本操作

STL还在bits\stl_iterator_base_funcs.h中定义了iterator的一些基本操作,主要包括以下几个:

distance

  • 函数声明:difference_type distance(InputIterator first,InputIterator last);

  • 作用: 求两个迭代器的距离

advance

  • 函数声明:void advance(InputIterator& i, Distance n);

  • 作用: 将迭代器i移动n个位置,n可以是负数(双向迭代器)

以下是c++11后增加的两个函数(参考MinGW g++4.8.1)

next

  • 函数声明:ForwardIterator next(ForwardIterator __x, difference_type __n = 1);

  • 作用:将迭代器x后移一位,并返回x。

prev

  • 函数声明:BidirectionalIterator prev(_BidirectionalIterator __x,difference_type __n = 1);

  • 作用:将双向迭代器x前移一位,并返回x。

上面的几个声明是简化的形式,具体实现时还需要修改。


框架的选择

应该包括哪些操作?应该把哪些操作交给容器?抽象到什么程度?考虑清楚这些问题,直接关系到后面的容器该的怎么设计。在比较了SGI STL和GNU gcc的迭代器设计之后,我决定采用gcc STL的的设计。gcc STL的设计中,container都有自己的iterator,所以一般以[container]::[iterator]的形式访问容器的iterator。这并不是说iterator都直接设计在container里面,虽然不同的容器需要不同的迭代器,但是我们可以对迭代器某些通用的属性和操作进行抽象。所以,迭代器是无法完全从容器中抽离出来单独设计,迭代器的设计主要包括通用抽象部分和具体容器部分。下面以gcc STL的vector的迭代器为例分析迭代器的实现:

TL的vector的迭代器为例分析迭代器的实现:
  • 通用的部分:

     在bits\stl_iterator_base_type.h和bits\stl_iterator_base_funcs.h中,包含了
     所有迭代器相关的类型(如iterator,iterator_traits),函数(如advance,distance)
    
  • 适配器:

     在bits\stl_iterator.h中基于前面的iterater,实现了一些iterator适配器,比如
     __normal_iterator,reverse_iterator等。
    
  • 容器部分:

     在bits\stl_vector.h中,使用__normal_iterator<pointer,Container>建立了一个
     vector专属的迭代器。
    

大致上,迭代器的设计包括以上的部分。但是也有特例,比如std::list的迭代器是在内部完全重新写过的。

经过各方面的考量和取舍,我将通用部分合在iterator_base.h中,将适配器写在stl_iterator.h中,主要实现_normal_iterator,其他的放到adapter部分。而容器部分就放到以后实现容器的时候再说。

完整代码

//my_iterator_base.h
#ifndef MY_ITERATOR_H_INCLUDED
#define MY_ITERATOR_H_INCLUDED
#include<iostream>
#include<typeinfo>             //for typeid
using std::cout;
using std::endl;
namespace juine
{
    //5个迭代器类型
    struct input_iterator_tag{};
    struct output_iterator_tag{};
    struct forward_iterator_tag:public input_iterator_tag,public output_iterator_tag{};
    struct bidirectional_iterator_tag:public forward_iterator_tag{};
    struct random_access_iterator_tag:public bidirectional_iterator_tag{};

    template<class T>
    class Iterator_base
    {
    public:
        //作为迭代器所必需的元素(萃取5元素)
        typedef T value_type;
        typedef T* pointer;
        typedef T& reference;
        typedef size_t difference_type;
        //iterator_category 需要根据迭代器的类别来判断


        //构造函数和析构函数
        Iterator_base(T* p=0):point(p){}
        //copy构造函数怎么写:
        Iterator_base(const Iterator_base& t):point(t.point){}
        ~Iterator_base(){delete point;}

        //实现*和->的引用,++
        value_type& operator*(){ return *point; }
        pointer operator->(){ return point; }
        Iterator_base operator++()
        {
            point++;
            return *this;
        }
        Iterator_base operator++(int)
        {
            Iterator_base tmp(*this);
            ++*this;
            return tmp;
        }

        bool operator!=(Iterator_base iter)
        {
            if(point==iter.point)
                return true;
            return false;
        }



    private:
        T* point;
    };

    //萃取出迭代器中的各个性质
    template<class T>
    struct strait
    {
        //不能写成其他的 ,因为要和标准的STL实现无缝链接
        typedef typename T::value_type value_type;
        typedef typename T::reference reference;
        typedef typename T::difference_type difference_type;
        typedef typename T::pointer pointer;
        typedef typename T::iterator_category iterator_category;

    };
    //偏特化
    template<class T>
    struct strait<T*>
    {
        typedef T value_type;
        typedef T& reference;
        typedef T* pointer;
        typedef size_t difference_type;
        typedef random_access_iterator_tag iterator_category;
    };

    template<class T>
    struct strait<const T*>
    {
        typedef T value_type;
        typedef T& reference;
        typedef T* pointer;
        typedef size_t difference_type;
        typedef random_access_iterator_tag iterator_category;
    };

    //迭代器常见操作方法之advance方法
    template<class InputIterator>
    void __advance(InputIterator& iter,size_t n,input_iterator_tag )
    {
        while(n--)
            iter++;
        cout<<"调用的是InputIterator迭代器"<<endl;
    }

    template<class InputIterator>
    void __advance(InputIterator& iter,size_t n,forward_iterator_tag )
    {
        __advance(iter,n,InputIterator());
        cout<<"调用的是ForwardIterator迭代器";
    }
    template<class InputIterator>
    void __advance(InputIterator& iter,size_t n,bidirectional_iterator_tag )
    {
        if(n>0)
            while(n-->0)
                iter++;
        else
            while(n++>=0)
                iter--;
        cout<<"调用的是BidirectionalIterator迭代器"<<endl;
    }
    template<class InputIterator>
    void __advance(InputIterator& iter,size_t n,random_access_iterator_tag )
    {
        iter+=n;
        cout<<"调用的是RandomIterator迭代器"<<endl;
    }

    //对外统一的接口
    template<class InputIterator>
    void my_advance(InputIterator& iter,size_t n)
    {
        cout<<"自制advance"<<endl;
        typedef typename strait<InputIterator>::iterator_category iterator_category;
        __advance(iter,n,iterator_category());
    }

    //迭代器常见操作方法之distance方法
    template<class InputIterator>
    typename strait<InputIterator>::difference_type
    __distance(InputIterator iter1,InputIterator iter2,input_iterator_tag)
    {
        typedef typename strait<InputIterator>::difference_type difference_type;
        difference_type length=0;
        while(iter1!=iter2)
        {
            iter1++;
            length++;
        }
        return length;
    }

    template<class InputIterator>
    typename strait<InputIterator>::difference_type
    __distance(InputIterator iter1,InputIterator iter2,forward_iterator_tag)
    {
       return __distance(iter1,iter2,input_iterator_tag());
    }

    template<class InputIterator>
    typename strait<InputIterator>::difference_type
    __distance(InputIterator iter1,InputIterator iter2,random_access_iterator_tag)
    {
        typedef typename strait<InputIterator>::difference_type difference_type;
        difference_type length=iter2-iter1;
        return length;
    }
    //对外实现统一的接口
    template<class InputIterator>
    typename strait<InputIterator>::difference_type my_distance(InputIterator iter1,InputIterator &iter2)
    {
        typedef typename strait<InputIterator>::iterator_category iterator_category;
        typedef typename strait<InputIterator>::difference_type difference_type;
        difference_type length=__distance(iter1,iter2,iterator_category());
        return length;
    }





}
#endif // MY_ITERATOR_H_INCLUDED
测试代码

//test_iterator.cpp
#include<vector>
#include<iostream>
#include"my_iterator_base.h"
using namespace juine;
using namespace std;
int main()
{
    int a[5]={1,2,3,4,5};
    vector<int> vec(a,a+5);
    vector<int>::iterator iter=vec.begin();
    my_advance(iter,2);
    cout<<"my_advence调用后:"<<*iter<<endl;
    vector<int>::iterator iter2=vec.begin()+4;
    cout<<"distance距离为:"<<my_distance(iter,iter2);
    return 0;
}
测试结果截图:

bubuko.com,布布扣

从结果可以看出,该迭代器实现了对STL的无缝链接,基本上达到我们预期的结果!





迭代器实现,布布扣,bubuko.com

迭代器实现

原文:http://blog.csdn.net/bb2b2bbb/article/details/23169891

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!