迭代器相关概念总结
一、迭代器(Iterator)的定义以及功能。
1.1、迭代器是一种检查容器内元素并遍历元素的数据类型。Iterator(迭代器)模式又称Cursor(游标)模式
迭代器是一种设计模式。容器生成的迭代器用于遍历容器中的每个元素, 同时避免暴露容器的内部数据结构和实现细节。
(注意:Adaptor在设计模式上的定义:将一个class的接口转换为另一个class的接口,使得原本因为接口不兼容而
不能合作的classes可以一起工作)
迭代器还有一个非常纯粹的理念:任何东西,只要其行为类似迭代器,它就是一个迭代器。
1.2、迭代器的功能
1.指向容器中的元素,类似于指针。
2.作为容器与算法的媒介,也可以称作粘合剂。
二、迭代器类型,共有五种。
(1)Input iterator:输入迭代器
(2)Output iterator:输出迭代器
(3)Forward iterator:前向迭代器
(4)Bidirectional iterator:双向迭代器
(5)Random access iterator:随机访问迭代器
注意,容器适配器 stack、queue 和 priority_queue 没有迭代器。容器适配器有一些成员函数,可以用来对元素进行访问。
容器 迭代器功能
vector 随机访问
deque 随机访问
list 双向
set/multiset 双向
map/multimap 双向
stack 不支持迭代器
queue 不支持迭代器
priority_queue 不支持迭代
三、迭代器的使用。迭代器按照定义方式分成以下四种。
(1) 正向迭代器:容器类名::iterator 迭代器名;
(2) 常量正向迭代器:容器类名::const_iterator 迭代器名;
(3) 反向迭代器:容器类名::reverse_iterator 迭代器名;
(4) 常量反向迭代器:容器类名::const_reverse_iterator 迭代器名;
四、迭代器适配器主要分三类:
(1)插入适配器
4.1.1、back_inserter:安插于容器最尾端,back_inserter内部调用push_back() 因此需要容器支持push_back()操作,
这样的容器有三个:vector deque list
4.1.2、front_inserter:安插于容器最前端,需要容器支持push_front()操作,这样的容器只有deque和list
4.1.3、inserter:一般型安插迭代器,它将元素插入迭代器初始化时传入的第二参数所指位置的前方。Inserters内部调用
Insert()成员函数,因此支持所有的STL容器。也是唯一可用于关联式容器的安插迭代器。
(2)流迭代器适配器
2.1、输出流迭代器适配器ostream_iterator
2.2、输入流迭代器适配器istream_iterator
(3)逆向迭代器适配器reverse_iterator
五、STL迭代器失效问题
迭代器失效,有两个层面的意思,
(1) 无法通过迭代器++,--操作遍历整个stl容器。记作: 第一层失效。
(2) 无法通过迭代器存取迭代器所指向的内存。 记作: 第二层失效。
关于这个问题, 不同的容内器对应的结果是不同的。
vector
vector是个连续内存存储的容器,如果vector容器的中间某个元素被删除或从中间插入一个元素,有可能导致内存
空间不够用而重新分配一块大的内存。这个动作将导致先前获取的迭代器,第一层和第二层均失效。
map
map内部是红黑树结构,当map中新插入或删除元素后,树的结构会相应的调整。但是,通过先前的迭代器,仍然
可以通过++可以遍历map。 能遍历到值>当前迭代器的节点。迭代器指向的用户数容据内存始终有效。
list
同理map, 通过++只能遍历链表右侧的节点,迭代器指向的用户数据内存也始终有效。
小结
STL使用迭代器将算法和容器结合,利用迭代器型别可以针对不同迭代器编写更加高效的算法,这里一点很重要的
思想就是:利用C++重载机制和参数推导机制将运行期决议问题提前到编译期决议,也就是说,我们不需要在运行
时判断迭代器的类型,而是在编译期就已经决定。这很符合C++模板编程的理念。