沙田镇网站建设公司,网站建设属开票核定税种,医疗网站被黑后可以做排名,潍坊住房和城乡建设部网站在list的上一篇博客里实现了list基本的初始化、插入数据、删除数据的基本功能#xff0c;这些功能的实现方式只是在原先链表的实现里加入了模版而已#xff0c;但是list作为一个容器#xff0c;它还有一个基础的东西——迭代器。list的迭代器和之前实现的string和vector很大… 在list的上一篇博客里实现了list基本的初始化、插入数据、删除数据的基本功能这些功能的实现方式只是在原先链表的实现里加入了模版而已但是list作为一个容器它还有一个基础的东西——迭代器。list的迭代器和之前实现的string和vector很大不同这里就专门进行list迭代器基本功能的模拟实现。 list的迭代器本质上是一个指向list结点的一个指针但是因为list的结点在内存中的分布不是连续的所以如果直接用一个原生的指针作为迭代器的话在后续的操作中会有非常多的不同所以我们把指针也封装成一个类这样进行很多操作的时候就会更加方便。也是因为上面说的list的结点在内存中的分布不是连续的所以list迭代器并没有 、-这样的操作。 因为我们list本身就是一个模板类所以它的迭代器也一定要是一个模板类才能够匹配上迭代器的成员变量很简单就是一个指向list结点的一个指针所以在初始化的时候把这个某个结点赋值给成员变量即可。这个成员变量的类型一定是一个list结点的指针我们后续的操作也是根据这个指针来的所以这里我们typedef一下list_NodeTlist_NodeT就是list存储的数据的类型方便后续的操作。 templateclass Tstruct list_Iterator{typedef list_NodeT Node;Node* _node;list_Iterator(Node* node):_node(node){}} 首先基本的就是对迭代器的解引用操作和-操作了。这个解引用操作符的重载很常规只要返回这个内容的引用就行了但是-操作符的重载却没有那么简单。因为本身我们的迭代器本身本质上就是一个指针那么对这个指针用-那不是访问迭代器里的内容吗但是-不应该要访问到内内容里的嘛这样这个运算符重载不就改变了这个运算符的意义了吗。实际上在对迭代器使用-时编译器是把xxx..operator-()-自动优化成了一个-这样就能实现-原本的含义了所以-返回的一个是一个结点数据的指针因此才有了下面的写法。 T operator*(){return _node-_data;}//iterator.operator-()-...T* operator-(){return (_node-_data);} 和--操作的本质都是返回一个指向上一个或下一个结点的指针也就是返回一个迭代器为了方便操作我们也可以typedef一下自身的类型。list本身就是一个双向带头循环列表所以用迭代器指向的这个结点就能很轻松的找到前一个或后面一个结点。 typedef list_IteratorT Self;Self operator(){_node _node-_next;return *this;}Self operator--(){_node _node-_prev;return *this;} 判断运算符的重载就更简单了但是要注意的是我们要判断的是两个结点的地址是否相同吗不是比较结点存储的是否相同。 bool operator!(const Self s) const{return _node ! s._node;}bool operator(const Self s) const{return _node s._node;} 上面就完成了list迭代器的基本实现但是如果这样写的话我们会发现如果要实现const迭代器的话这样是不行的因为如果我们只是简单的在iterator前加上一个const是不能实现我们的要求的因为如果简单的用const修饰iterator的话这样变成了iterator的指向不能改变但是我们依旧可以修改iterator指向的那个结点保存的内容和我们const_iterator的要求指向可以改变但是不能改变所指的内容的要求完全不符所以不能直接这样简单的实现。 同时我们在实现iterator的时候返回值也有所不同这里就正好用模板就可以解决这个问题了首先我们的const_iterator的解引用操作是-时不允许修改内容的这里两种迭代器的不同需求我们可以通过模板解决第一步就是在给迭代器的模板增加两个模板参数其中Ref表示保存数据类型的引用Ptr表示保存数据类型的指针。解引用操作符重载的返回值类型用Ref代替-操作符重载的返回值用Ptr代替。 templateclass T,class Ref ,class Ptr 第二步在list类的内部增加两个typedefiterator就是一个正常的迭代器的类型不过因为是上一点的原因我们要多加两个模板参数而const_iterator的模板参数的类型则有变化因为const_iterator的指向是可以改变的所以要在模板参数里加上const把const加在T之前这样在迭代器里使用解引用操作符和-操作符的时候就不能对保存的数据进行操作了这样就实现了代码的复用。 typedef list_IteratorT,T,T* iterator;typedef list_IteratorT,const T,const T* const_iterator;