迭代器
  容器和算法的胶合剂,是一种“泛型指针”

  1. 五种迭代器    

(1)输入迭代器          只能读,不能写          只支持自增    

(2)输出迭代器          只能写,不能读          只支持自增   

(3)前向迭代器          读 / 写                         只支持自   

(4)双向迭代器          读 / 写                         自增和自减   

(5)随机迭代器          读 / 写                         支持完整迭代器算术运算   

输入迭代器: 可用于读取容器中的元素,但是不能保证能支持容器的写入操作。输入迭代器必须至少提供下列支持。相等== 和不相等 !=,比较两个迭代器。前置和后置的                        自增运算,使迭代器去向前递进指向下一个元素。用于读取元素的解引用操作符(*),此操作符只能出现在赋值运算的右操作数上

输出迭代器:可视为与输入迭代器功能互补的迭代器,输出迭代器可用于向容器写入元素,但是不保证能支持读取容器内容,输出迭代器要求:
      前置和后置的自增运算(++),使迭代器向前递进指向下一个元素
      解引用操作符(*),解引用操作符智能出现在赋值运算的左操作数上。给解引用的输出迭代器赋值,将对该迭代器所指向的元素做写入操作。输出迭代器可以要求每个迭代器值必须正好写入一次。使用输出迭代器时,对于指定的迭代器应该使用一次*运算,而且只能用一次。输出迭代器一般用作算法的第三个实参,标记起始写入的位置。例如,copy 算法使用一个输出迭代器作为它的第三个实参,将输入范围内的元素复制到输出迭代器指定的目标位置。标准库 ostream_iterator 类型输出迭代器。
前向迭代器:用于读写指定的容器。这类迭代器只会以一个方向遍历序列。前向迭代器支持输入迭代器和输出迭代器提供的所有操作,除此之外,还支持对同一个元
                               素的多次读写。可复制前向迭代器来记录序列中的一个位置,以便将来返回此处。需要前向迭代器的泛型算法包括replace。
双向迭代器:从两个方向读写容器。
          除了提供前向迭代器的全部操作之外,双向迭代器还提供前置和后置的自减运算(--)。需要使用双向迭代器的泛型算法包括 reverse。
所有标准库容器提供的迭代器都至少达到双向迭代器的要求。
随机访问迭代器:提供在常量时间内访问容器任意位置的功能。这种迭代器除了支持双向迭代器的所有功能之外,还支持下面的操作:
         关系操作符 <、<=、> 和 >=,比较两个迭代器的相对位置。迭代器与整型数值 n 之间的加法和减法操作符 +、+=、- 和 -=,结果是迭代器在容器中向前(或退回)n 个元素。两个迭代器之间的减法操作符(--),得到两个迭代器间的距离。下标操作符 iter[n], 这是 *(iter + n) 的同义词。需要随机访问迭代器的泛型算法包括 sort 算法。vector、deque 和string 迭代器是随机访问迭代器,用作访问内置数组元素的指针也是随机访问迭代器。除了输出迭代器,其他类别的迭代器形成了一个层次结构:需要低级类别迭代器的地方, 可使用任意一种更高级的迭代器。对于需要输入迭代器的算法,可传递前向、双向或随机访问迭代器调用该算法。调用需要随机访问迭代器的算法时,必须传递随机访问迭代器。


map、set 和 list 类型提供双向迭代器,而 string、vector 和 deque 容器上定义的迭代器都是随机访问迭代器都是随机访问迭代器,用作访问内置数组元素的指针也是随机访问迭代器。istream_iterator 是输入迭代器,而ostream_iterator 则是输出迭代器。

容器 支持迭代器的类别 说明
vector 随机访问 一种随机范围的数组类型,提供了对数组元素进行快速随机访问以及序列尾部进行快速的插入和删除操作的功能
deque 随机访问 一种随机访问的数组类型,提供了序列两端快速进行插入和删除操作的功能,可以在需要时候修改自身的大小
list 双向 一种不支持随机访问的数组类型,插入和删除花费的时间是固定的,与位置无关
set 双向 一种随机存取的容器,其关键字和数据元素是同一个值,所有元素必须有唯一值
multiset 双向 一种随机存取的容器,其关键字和数据元素是同一个值,可以包含重复的元素
map 双向 一种包含成对数值的容器,一个值是实际数据值,另一个是用来寻找数据的关键字。一个特定的关键字只能与一个元素关联
multimap 双向 一种包含成对数值的容器,一个值是实际数据值,另一个是寻找数据的关键字。一个关键字可以与多个数据相关联
stack 不支持 适配器容器类型,用vector,deque或list对象创建一个先进后出的容器
queue 不支持 适配器容器类型,用deque或list对象创建一个先进先出的容器
priority_queue 不支持 适配器容器类型,用vector或deque对象创建一个排序队列

 

 

迭代器失效
迭代器失效分三种情况考虑,也是分三种数据结构考虑,分别为数组型,链表型,树型数据结构。

数组型数据结构:该数据结构的元素是分配在连续的内存中,insert和erase操作,都会使得删除点和插入点之后的元素挪位置,所以,插入点和删除掉之后的迭代器全部失效,也就是说insert(*iter)(或erase(*iter)),然后在iter++,是没有意义的。解决方法:erase(*iter)的返回值是下一个有效迭代器的值。 iter =cont.erase(iter);

链表型数据结构:对于list型的数据结构,使用了不连续分配的内存,删除运算使指向删除位置的迭代器失效,但是不会失效其他迭代器.解决办法两种,erase(*iter)会返回下一个有效迭代器的值,或者erase(iter++).

树形数据结构: 使用红黑树来存储数据,插入不会使得任何迭代器失效;删除运算使指向删除位置的迭代器失效,但是不会失效其他迭代器.erase迭代器只是被删元素的迭代器失效,但是返回值为void,所以要采用erase(iter++)的方式删除迭代器。

注意:经过 erase(iter) 之后的迭代器完全失效,该迭代器 iter 不能参与任何运算,包括 iter++,*ite