STL相关知识整理(二) iterator
五种迭代器类型
注意,容器适配器 stack、queue 和 priority_queue 没有迭代器。
output迭代器支持操作
input迭代器
forward迭代器
bidirectional(双向)迭代器
random-access迭代器
迭代器与指针
迭代器不是指针,是类模板,表现的像指针。他只是模拟了指针的一些功能,通过重载了指针的一些操作符,->、*、++、--等。迭代器封装了指针,是一个“可遍历STL( Standard Template Library)容器内全部或部分元素”的对象, 本质是封装了原生指针,是指针概念的一种提升(lift),提供了比指针更高级的行为,相当于一种智能指针,他可以根据不同类型的数据结构来实现不同的++,--等操作。
迭代器辅助函数
STL 中有用于操作迭代器的三个函数模板,它们是:
- advance(p, n):使迭代器 p 向前或向后移动 n 个元素。
- distance(p, q):计算两个迭代器之间的距离,即迭代器 p 经过多少次 + + 操作后和迭代器 q 相等。如果调用时 p 已经指向 q 的后面,则这个函数会陷入死循环。
- iter_swap(p, q):用于交换两个迭代器 p、q 指向的值
const_iterator 和 reverse_iterator
const_iterator 对象可以用于const vector 或非 const vector,它自身的值可以改(可以指向其他元素),但不能改写其指向的元素值
迭代器失效
插入
序列容器
-
vector
:插入点之前的所有迭代器和引用都不受影响,除非新容器大小大于先前的容量(在这种情况下,所有迭代器和引用都无效)[23.3.6.5/1] -
deque
:所有迭代器和引用都是无效的,除非插入的成员位于双端队列的末尾(前面或后面)(在这种情况下,所有迭代器都无效,但对元素的引用不受影响)[23.3.3.4/1] -
list
:所有迭代器和引用不受影响[23.3.5.4/1] -
forward_list
:所有迭代器和引用不受影响(适用于insert_after
) [23.3.4.5/1] -
array
:(不适用)
关联容器
-
[multi]{set,map}
:所有迭代器和引用不受影响[23.2.4 / 9]
未分类的关联容器
-
unordered_[multi]{set,map}
:发生重新散列时所有迭代器都无效,但引用不受影响[23.2.5 / 8]。如果插入不会导致容器的大小超过不发生重散列z * B
,其中z
为最大负载因数和B
桶的当前数目。[23.2.5 / 14]
容器适配器
-
stack
:继承自底层容器 -
queue
:继承自底层容器 -
priority_queue
:继承自底层容器
擦除
序列容器
-
vector
:擦除点或之后的每个迭代器和引用都无效[23.3.6.5/3] -
deque
:擦除最后一个元素只会使迭代器和对擦除元素的引用和过去的迭代器无效; 擦除第一个元素只会使迭代器和对擦除元素的引用无效; 擦除任何其他元素会使所有迭代器和引用无效(包括过去的迭代器)[23.3.3.4/4] (注:在其首部或尾部删除元素则只会使指向被删除元素的迭代器失效) -
list
:只有迭代器和对擦除元素的引用无效[23.3.5.4/3] -
forward_list
:只有迭代器和对擦除元素的引用无效(适用于erase_after
) [23.3.4.5/1] -
array
:(不适用)
关联容器
-
[multi]{set,map}
:只有迭代器和对擦除元素的引用无效[23.2.4 / 9]
无序的关联容器
-
unordered_[multi]{set,map}
:只有迭代器和对擦除元素的引用无效[23.2.5 / 13]
容器适配器
-
stack
:继承自底层容器 -
queue
:继承自底层容器 -
priority_queue
:继承自底层容器
迭代器失效分三种情况考虑,也是分三种数据结构考虑,分别为数组型,链表型,树型数据结构。
数组型数据结构:该数据结构的元素是分配在连续的内存中,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