迭代器基本介绍:

STL的设计中心思想在于:将容器和算法分开,彼此独立设计,最后再以一个胶合剂连接在一起。而算法和数据容器的泛型化从技术角度来说并不难实现,而如何将两者联系起来才是问题的关键所在。而迭代器恰恰扮演者这个角色。迭代器定义的位置最好是在容器内,将定义的任务交给了容器的设计者,因为每一种容器都对应一种迭代器,而定义在内部也不会暴露容器的内部元素。

看看下面的find函数:

可以看出find接受两个迭代器和一个目标对象。只要给予不同的迭代器find就可以对不同的容器进行查找了。

迭代器是一种类似指针的对象,而指针的各种行为中最常见也是最重要的便是内容提领和成员访问。因此,迭代器最重要的编程工作就是对operator*和operator->进行重载。

在学习数据结构的时候list一直是一个重点,以前也曾模拟实现过list,如今何不为list设计一个迭代器来将其数据容器与算法粘合起来呢?

其接口及结点实现如下:

 template <class T>
struct __ListNode
{__ListNode<T>* _next;__ListNode<T>* _prev;T _data;__ListNode(const T& x = T()):_next(NULL), _prev(NULL), _data(x){}
};template <class T>
class List
{
public:typedef __ListNode<T> Listnode;List(){_head = new Listnode;_head->_next = _head;_head->_prev = _head;}~List(){}void Insert(const T& x);Iterator Erase(const T& x);protected:Listnode* _head;};

       模拟实现简化版:

我们自己实现的List也可以套用find函数,只需对其进行一个迭代器的设计就OK了。

具体实现如下:

template<class T,class Ref,class Ptr>
struct __ListIterator
{typedef __ListIterator<T, Ref, Ptr> Self;typedef T ValueType;typedef Ptr Pointer;typedef Ref Reference;__ListNode<T>* _node;__ListIterator(__ListNode<T>* x):_node(x){}__ListIterator(){}bool operator==(const Self& s){return _node == s._node;}bool operator!=(const Self& s){return _node != s._node;}Reference operator*(){return _node->_data;}/*Reference operator->(){return _node->_data;}*/Self& operator++()           //前置{_node = _node->_next;return *this;}Self& operator++(int)            {Self tmp(*this);_node = _node->_next;return tmp;}Self& operator--(){_node = _node->_prev;return *this;}Self& operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}
};

       迭代器型别和trait编程:

迭代器的型别主要有五种:value_type,catalog,reference,pointer,diffrence。分别代表这迭代器所指对象类型,迭代器类型,迭代器所指类型引用,迭代器所指类型指针,用什么类型表示迭代器之间距离(如int类型)。

这里就不得不说下STL里面为了提取这些迭代器都有的特性用到的一个技法——trait。

STL为所有的迭代器提供一个型别类型,我们每定义一个迭代器都必须继承该型别类型,这样就可以保证符合STL的规范,防止遗漏。

template <class Category, class T, class Distance = ptrdiff_t,  class Pointer = T*, class Reference = T&>
struct iterator {  typedef Category  iterator_category;  typedef T         value_type;  typedef Distance  difference_type;  typedef Pointer   pointer;  typedef Reference reference;
};

当定义迭代器的时候,必须给定迭代器的特性。STL为提取迭代器的特性,提供了一个模板类iterator_trait,适用于所有的迭代器和原生指针。

指针并非类型,因此需要偏特化成一个模板对应指针的特性,可以看出,指针是随机访问迭代器类型。

迭代器的类型有五种:输入、输出、前向、双向、随机访问五种迭代器,输入和输出分别只读和只写,只能向前不能向后,前向迭代器可以进行读写,只能向前,双向迭代器可以向前和向后移动,但每次只能移动一次,随机访问迭代器可以跳跃移动,与原生指针操作相同。

STL中构建了这五种类别,用于标识迭代器的类别。

struct input_iterator_tag {};
struct output_iterator_tag {};
struct forward_iterator_tag : public input_iterator_tag {};
struct bidirectional_iterator_tag : public forward_iterator_tag {};
struct random_access_iterator_tag : public bidirectional_iterator_tag {};

可以看出继承关系,使用template元编程技术,之所以使用结构体或类,是为了进行参数推导,将判断在编译期执行而非运行期,因为每个迭代器操作不同,因此需要不同的函数版本对应不同迭代器。

以上讲的是迭代器的特性提取,还有类型的特性提取。类型的型别主要有五种:has_trivial_default_constructor、has_trivial_copy_constructor、has_trivial_assignment_operator、has_trivial_destructor、is_POD_type。

        迭代器失效:

迭代器就不得不提到一个问题,迭代器失效。

以vector为例,当我们插入一个元素时它的预分配空间不够时,它会重新申请一段新空间,将原空间上的元素复制到新的空间上去,然后再把新加入的元素放到新空间的尾部,以满足vector元素要求连续存储的目的。而后原空间会被系统撤销或征做他用,于是指向原空间的迭代器就成了类似于“悬垂指针”一样的东西,指向了一片非法区域。如果使用了这样的迭代器会导致严重的运行时错误就变得很自然了。这就是由迭代器失效引起的。当然删除一个元素时也可能引起迭代器失效。erase操作是在原空间上进行的,假设有一个存有"12345"序列的vector<int>容器原本指向3的迭代器在我删除2之后就变成指向4了。

说了这么多似乎可以归纳一下迭代器失效的类型了:
      1.由于容器元素整体“迁移”导致存放原容器元素的空间不再有效,从而使得指向原空间的迭代器失效。

2.由于删除元素使得某些元素次序发生变化使得原本指向某元素的迭代器不再指向希望指向的元素。

转载于:https://blog.51cto.com/luminous/1828440

迭代器——STL关键所在相关推荐

  1. C++中的迭代器(STL迭代器)iterator

    1.Cpp中的迭代器 要访问顺序容器和关联容器中的元素,需要通过迭代器(iterator)进行.迭代器是一个变量,相当于容器和操纵容器的算法之间的中介.迭代器可以指向容器中的某个元素,通过迭代器就可以 ...

  2. c++ stl 容器 迭代器 stl用法示例

    1.基本概念 1.1容器概述 顺序容器 vector, deque,list 关联容器 set, multiset, map, multimap 容器适配器 stack, queue, priorit ...

  3. 【STL源码剖析】迭代器

    [STL源码剖析]迭代器 第3章 迭代器(iterators)与traits编程技法(<STL源码剖析> ) 3.1 迭代器设计思维--STL关键所在 3.2 迭代器(iterator)是 ...

  4. C++ 笔记(19)— 标准模板库(STL容器、STL迭代器、STL算法、STL容器特点、STL字符串类)

    C++ 标准库可以分为两部分: 标准函数库: 这个库是由通用的.独立的.不属于任何类的函数组成的.函数库继承自 C 语言. 面向对象类库: 这个库是类及其相关函数的集合. C++ 标准库包含了所有的 ...

  5. 第三章 迭代器(iterators)概念与traits编程技法

    迭代器(iterators)概念与traits编程技法 3.1 迭代器设计思想--STL关键所在 3.2 迭代器(iterators)是一种smart pointe 3.3 迭代器相应型别(assoc ...

  6. 数据结构利器之私房STL

    此系列的文章适合初学有意剖析STL和欲复习STL的同学们.都是原创! 学过c++的同学相信都有或多或少接触过STL.STL不仅仅是c++中很好的编程工具(这个词可能有点歧义,用类库更恰当),还是学习数 ...

  7. [技术] OIer的C++标准库 : STL入门

    注: 本文主要摘取STL在OI中的常用技巧应用, 所以可能会重点说明容器部分和算法部分, 且不会讨论所有支持的函数/操作并主要讨论 C++11 前支持的特性. 如果需要详细完整的介绍请自行查阅标准文档 ...

  8. C++ stack,queue(补充):deque,反向迭代器

    目录 1.deque​编辑 2.反向迭代器 1.deque vector和list的优缺点  效率比较 2.反向迭代器 和正向迭代器相比,除了++/--时方向相反,其他操作基本一致.下面为list的反 ...

  9. STL源码剖析之配接器

    adapter(配接器)在STL组件的灵活组合运用上,扮演者转换器的角色.adapter来源于一种适配器模式,其功能是:将一个class接口转换为另一个class的接口,使得原本因接口不兼容而不能合作 ...

最新文章

  1. 008-SDK框架之LYWSDKPlatformManager.h
  2. JavaScript 32位整型无符号操作
  3. 【☀️Linux什么姿势最舒服?简单讲讲☀️】嵌入式Linux入门
  4. python清洗数据用什么包_格式化和清洗数据的Python工具包
  5. 如何优化JavaScript脚本的性能
  6. Luogu P3731 [HAOI2017]新型城市化
  7. 如果你跟夕小瑶恋爱了...(下)
  8. 炉石整活拔线方法_酒馆战棋:整活如何简单“拔线”?瓦娘在线教学,却3本得死神?...
  9. Ubuntu16.04上使用Anaconda3的Python3.6的pip安装UWSGI报错解决办法
  10. Pytorch 操作整理
  11. 计算机专业课题 结题报告,计算机结题报告.doc
  12. UVM学习整理——UVM整体介绍
  13. 微信web开发者工具、网易云音乐、为知笔记等软件崩溃无法打开等问题的解决
  14. 使用Python将一个excel的某些内容导入到新的excel中
  15. R语言生存分析中的OR值是什么?如何解读?
  16. 金融时报:去赚8亿非网民的钱
  17. Qt 通过条件编译区分Debug和Release代码
  18. [附源码]java毕业设计高铁售票管理系统
  19. C++和G++的区别
  20. 视频融合平台EasyCVR接入海康SDK时无法播放录像该如何解决?

热门文章

  1. JavaScript Promise查缺补漏
  2. C#操作DOS命令,并获取处理返回值
  3. javascript expando
  4. 自由职业者:5步拿下新项目
  5. 多浏览器下,CSS截断功能。
  6. 国外值得关注的网站系列之二-社交化推荐网站GetGlue
  7. oracle索引的监控
  8. 常见的两大交换机硬故障
  9. ScheduledThreadPoolExecutor定时任务线程池
  10. linux socket 加锁,Linux使用openssl对socket加密【1】