STL——迭代器

理解迭代器是学习STL的必经之路,迭代器可以看做是指针的抽象,相当于指针,不同的是,迭代器将指针的操作抽象出来,使之能适应不同数据类型,不同的容器类型。比如,常见的数组和链表,数组是连续存储的,而链表则不是,对于遍历操作,相同的是都需要从起始地址开始,到结束,不同的是operator++()的具体实现形式不同。如果能够将访问不同容器类型的指针抽象出来,就可以将容器与算法分离。

下面是一个为数组容器、链表容器编制共同显示函数的例子,通过这个例子,可以帮助我们更好的理解迭代器。
代码如下:

#include "stdafx.h"
#include<iostream>
#include<numeric>
using namespace std;
//动态数组的模板类
template<class T>
class Array
{
public:
    Array(size_t n=3):m_nTotalSize(3),m_nValidSize(0){
        m_pData=new T[n];
    }
    virtual ~Array(){
        if(m_pData){
            delete []m_pData;
            m_pData=NULL;
        }
    }
    void Add(const T& e){
        if(m_nValidSize<m_nTotalSize){
            m_pData[m_nValidSize]=e;
            ++m_nValidSize;
        }
        else{
            m_nTotalSize<<=1;       //容量扩展1倍
            T* tmp=new T[m_nTotalSize];
            memcpy(tmp,m_pData,m_nValidSize*sizeof(T));//重新分配内存空间
            tmp[m_nValidSize]=e;
            delete []m_pData;//将原内存空间删除
            m_pData=tmp;
            ++m_nValidSize;
        }
    }
    size_t size() const{
        return m_nValidSize;
    }
    T Get(int pos){
        return m_pData[pos];
    }
    T* begin(){//起始迭代指针
        return m_pData;
    }
    T* end(){//终止迭代指针
        return m_pData+m_nValidSize;
    }

private:
    int m_nTotalSize;   //总容量
    int m_nValidSize;   //有效容量
    T* m_pData;         //数据
};
//Array对应的迭代器类
template<class Init>
class ArrayIterator
{
public:
    ArrayIterator(Init* i):init(i){}
    bool operator !=(ArrayIterator& it){
        return it.init!=init;
    }
    void operator++(int){//后置迭代指针
        init++;
    }
    Init operator*(){
        return *init;
    }

protected:
    Init* init;
};
//泛型显示函数,模板参数Init是一个指针
template<class Init>
void display(Init start,Init end)
{
    cout<<endl;
    for(Init mid=start;mid!=end;mid++)
    {
        cout<<*mid<<"\t";
    }
    cout<<endl;
}
template<class T>
struct Node
{
    Node():next(NULL){}
    Node(const T& e):data(e),next(NULL){}
    T data;
    Node* next;
};

//单向链表类
template<class T>
class List
{
public:
    List():head(NULL),tail(NULL),prev(NULL){}
    ~List(){
        if(head!=NULL){
            Node<T>* prev=head;
            Node<T>* next=NULL;
            while(prev!=NULL){
                next=prev->next;
                delete prev;
                prev=next;
            }
        }
    }
    void Add(const T& e){
        Node<T>* u=new Node<T>(e);
        if(NULL==head){
            head=u;
            prev=u;
        }
        else{
            prev->next=u;
            prev=u;
        }
        tail=u->next;
    }
    Node<T>* begin(){//起始迭代指针
        return head;
    }
    Node<T>* end(){//终止迭代指针
        return tail;
    }

protected:
    Node<T>* head;  //链表头
    Node<T>* tail;  //链表尾
    Node<T>* prev;  //当前节点
};

//重载operator<<
template<class T>
ostream& operator<<(ostream& os,Node<T>&s)
{
    os<<s.data;
    return os;
}
//测试代码
int _tmain(int argc, _TCHAR* argv[])
{
    Array<int> a;
    for(int i=0;i<5;i++)
    {
        a.Add(i+1);
    }
    for(int i=0;i<5;i++)
    {
        cout<<a.Get(i)<<" ";
    }
    ArrayIterator<int> start(a.begin());
    ArrayIterator<int> end(a.end());
    display(start,end);

    List<int> b;
    for(int i=0;i<5;i++)
    {
        b.Add(i+1);
    }
    ListIterator<Node<int>> lstart(b.begin());
    ListIterator<Node<int>> lend(b.end());
    display(start,end);


    return 0;
}

以上代码实现了共同的显示函数,分别通过ArrayIteraror与ListIterator连接Array、List与display显示函数。
以上代码中ArrayIterator只能用在Array中,ListIterator只能用在List中,特定的容器,有特定的访问方式,应该有特定的迭代器,更合理的我们应该将ArrayIterator作为Array类的内部类,ListIterator作为List类的内部类。把迭代器类作为容器类的内部类。
代码如下所示:

//单向链表类
template<class T>
class List
{
public:

    //List对应的迭代器类
    class ListIterator
    {
    public:
        ListIterator(Node<T>* i):init(i){}
        bool operator !=(ListIterator& it){
            return it.init!=init;
        }
        void operator++(int){//后置迭代指针
            init=init->next;
        }
        Node<T> operator*(){
            return *init;
        }
    protected:
        Node<T>* init;
    };


    List():head(NULL),tail(NULL),prev(NULL){}
    ~List(){
        if(head!=NULL){
            Node<T>* prev=head;
            Node<T>* next=NULL;
            while(prev!=NULL){
                next=prev->next;
                delete prev;
                prev=next;
            }
        }
    }
    void Add(const T& e){
        Node<T>* u=new Node<T>(e);
        if(NULL==head){
            head=u;
            prev=u;
        }
        else{
            prev->next=u;
            prev=u;
        }
        tail=u->next;
    }
    Node<T>* begin(){//起始迭代指针
        return head;
    }
    Node<T>* end(){//终止迭代指针
        return tail;
    }

protected:
    Node<T>* head;  //链表头
    Node<T>* tail;  //链表尾
    Node<T>* prev;  //当前节点
};
测试代码2
int _tmain(int argc, _TCHAR* argv[])
{
    Array<int> a;
    for(int i=0;i<5;i++)
    {
        a.Add(i+1);
    }
    for(int i=0;i<5;i++)
    {
        cout<<a.Get(i)<<" ";
    }
    ArrayIterator<int> start(a.begin());
    ArrayIterator<int> end(a.end());
    display(start,end);

    List<int> b;
    for(int i=0;i<5;i++)
    {
        b.Add(i+1);
    }
    List<int>::ListIterator lstart(b.begin());//list<int>::iterator it=c.begin();有没有熟悉的感觉
    List<int>::ListIterator lend(b.end());
    display(lstart,lend);


    return 0;
}

到这里,就基本理解迭代器的实现过程了,以及为什么要有迭代器,它的作用是什么。

下面的代码是STL中的迭代器的使用。
STL迭代器代码示例:

#include "stdafx.h"
#include<iostream>
#include<numeric>
#include<list>
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
    list<int> c(10);
    std::iota(c.begin(),c.end(),1);
    list<int>::iterator it=c.begin();//迭代器
    for(;it!=c.end();it++)
    {
        cout<<*it<<" ";
    }
    return 0;
}

部分STL源码

//链表节点定义
template<class _Value_type,
    class _Voidptr>
    struct _List_node
        {   // list node
        _Voidptr _Next; // successor node, or first element if head
        _Voidptr _Prev; // predecessor node, or last element if head
        _Value_type _Myval; // the stored value, unused if head

    private:
        _List_node& operator=(const _List_node&);
        };
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值