设计1.0 -- iterator 和const_iterator底层的模拟实现

本文概要:

本文主要是模拟实现STL中迭代器和const迭代器的,主要阐述的一个问题就是,为什么我们在设计迭代器的时候需要使用三个模板参数呢

在设计迭代器的时候,我们有下面的代码

#include
using namespace std;

template<class T>
struct _ListNode
{
    _ListNode* _next;
    _ListNode* _prev;
    T _data;
    _ListNode(T d = 0)
        :_data(d)
        , _next(NULL)
        , _prev(NULL)
    {}
};


//这个T标记的是维护的数据类型,Ref是引用,这个引用是对数据的引用,就是这里面data的引用
//Ptr是指针,这个指针也是指向数据data的指针这两个模板类型我们可以在
//List这个类里面使用,因为在编写List_Iterator的时候,会经常使用Ref和Ptr
template<class T, class Ref, class Ptr>
class List_Iterator
{
    typedef _ListNode Node;
    typedef List_Iterator Self;   //这个地方写的 有点失误了,就是把List_Iterator的单词写错了
public:
    List_Iterator(Node* it)
        :_it(it)
    {}

    //List_Iterator& operator++()
    Self& operator++()
    {
        _it = _it->_next;
        return *this;
    }

    Self operator++(int)    //注意前置++返回的是引用,而后置++返回的是Self
    {
        Node* tmp = _it;
        _it = _it->_next;
        return tmp;
    }

    //T& operator*()
    Ref operator*()
    {
        return _it->_data;
    }

    bool operator!=(const Self& it)
    {
        return _it != it._it;    //一开始写这个!=运算符重载的时候也出现了错误,就是我一开始是拿this和&it比
                                //这显然是不对的,两个迭代器不可能是相等的,所以这个时候应该是拿
                                //这两个迭代器所指向的内容来比较,就是那他们的成员变量来 进行比较才正确
    }

private:
    Node* _it;
};


//这里我们需要做一个修改就是,我们需要把这个链表定义成一个双向的有头的循环链表
//这个工作就是要在构造函数的时候去做了
//所以这里_tail就不需要了



//有头结点,_head维护了一个头结点,但是这个节点不放置任何的数据,因为这样在后面的增删查改的时候使用的时候会非常的方便
template<class T>
class _List
{
    typedef _ListNode Node;

public:
    typedef List_Iterator Ierator;
    //const迭代器
    typedef List_Iteratorconst T&, const T*> Const_Ierator;

    _List()
        :_head(new Node)   //这里报了一个错误就是,没有合适的构造函数可以使用,原因是我上面写_ListNode的时候
        //传参了,但是这里没有传参数,所以我上面的额时候把传递的参数默认为d = 0这个时候就算是我不传递参数
        //也没有什么问题了
        //  , _tail(_head)
    {
        _head->_next = _head;
        _head->_prev = _head;
    }



    Node* begin()
    {
        if (_head->_next == _head)   //这里做了一个判断就是当我们的链表是空的时候,就不能直接返回next
        {
            return NULL;
        }
        return _head->_next;
    }



    Node* end()
    {
        if (_head->_next == _head)
        {
            return NULL;
        }
        return _head;
    }


    void Pushback(const T& data)
    {
        Node* cur = new Node(data);
        cur->_prev = _head->_prev;
        _head->_prev = cur;
        cur->_next = _head;
        cur->_prev->_next = cur;

    }

    void Print()
    {
        Const_Ierator it = begin();   //这个原因是,我们的begin不是 const的,但是我们的const_ietator是const的
        while (it != end())
        {
            cout << *it << endl;
            it++;
        }
    }
private:
    Node* _head;
//  Node* _tail;
};

void TestList()
{
    _List<int> l;
    l.Pushback(0);   //一开始的时候,我这里设置的这个参数是引用,这个时候是辩不过的,因为我们的0是在常量区的
    l.Pushback(1);
    l.Pushback(2);

    /*_List::Ierator it = l.begin();
    cout << *it << endl;
    ++it;
    cout << *it << endl;
    ++it;
    cout << *it << endl;*/
    _List<int>::Ierator it = l.begin();
    *it = 5;
    l.Print();

}




这里想重点比较一下普通迭代器和const迭代器,这里我们想看我们的普通迭代器的定义,

template<class T, class Ref, class Ptr>
class List_Iterator
{
    typedef _ListNode Node;
    typedef List_Iterator Self;   //这个地方写的 有点失误了,就是把List_Iterator的单词写错了
public:
    List_Iterator(Node* it)
        :_it(it)
    {}

    //List_Iterator& operator++()
    Self& operator++()
    {
        _it = _it->_next;
        return *this;
    }

    Self operator++(int)    //注意前置++返回的是引用,而后置++返回的是Self
    {
        Node* tmp = _it;
        _it = _it->_next;
        return tmp;
    }

    //T& operator*()
    Ref operator*()
    {
        return _it->_data;
    }

    bool operator!=(const Self& it)
    {
        return _it != it._it;    //一开始写这个!=运算符重载的时候也出现了错误,就是我一开始是拿this和&it比
                                //这显然是不对的,两个迭代器不可能是相等的,所以这个时候应该是拿
                                //这两个迭代器所指向的内容来比较,就是那他们的成员变量来 进行比较才正确
    }

private:
    Node* _it;
};

这里只是一个普通的迭代器的实现,一开始我一直疑惑的一个问题就是,为什么这里在设计的时候需要设计三个模板参数 呢,因为是为了实现迭代器的复用,这个时候还是需要看一下我们的list中对于迭代器的使用

class _List
{
    typedef _ListNode Node;

public:
    typedef List_Iterator Ierator;
    //const迭代器
    typedef List_Iteratorconst T&, const T*> Const_Ierator;

    _List()
        :_head(new Node)   

这里我只截图了迭代器的一部分,想看全部的可以从上面来看,这里需要定义一个普通的迭代器的时候,使用typedef List_Iterator

Ref operator*()
    {
        return _it->_data;
    }

因为我们在list中使用的时候是按照下面的形式进行组织的

typedef List_Iteratorconst T&, const T*> Const_Ierator;

所以在上面的那个Ref operator*()里面 返回值就变成了const的,这个时候const_iterator所指向的内容就不可变了

你可能感兴趣的:(C++,关于设计,iterator,设计,迭代器)