Cpp_STL_iterator
内容
- iterator的分类
- iterator的属性
- advance–使迭代器移动n步
- 针对迭代器的类型萃取
- SGI萃取的写法
- distance–计算两迭代器之间的距离
iterator
1 |
|
1 | template<class _Iterator> |
advance
1 | inline void advance(_II& i, _D n) |
萃取器
首先是针对泛型iterator,其是标准的迭代器,重载了*和->运算符。这里的萃取器可容纳的不包括裸指针。
1 | template<class _Iterator> |
接下来是针对裸指针作出的模板特化。裸指针可看作是可随机访问的迭代器。
1 | template<class T> |
接着再次对裸指针的萃取器模板作出部分特化,可处理常裸指针。
1 | template<class T> |
至此代码版本v1
1 |
|
SGI的做法
1 | //以下三个函数是SGI比较重要的写法模式 |
1 | template<class _II, class _D> |
distance
1 | template<class _II> |
迭代器失效的场景
可以指向元素的工具:迭代器、指针和引用。有时,虽然迭代器失效,但指针和引用不一定失效。
除了元素的迭代器失效的问题,还要考虑容器end这个迭代器是否失效的问题。end() 特性:只要元素数变了,之前拿到的 end() 立刻失效。
vector、string
- 只要涉及到扩容,全部迭代器都会失效(包括迭代器、指针和引用)。
- insert、push_back:之后,插入点(插入后,放的是新元素)到末尾,这一范围全失效(迭代器、指针和引用)。插入点之前的不受影响。
end()迭代器失效
- erase:之后,删除点(删除后,放的是下一个元素)到末尾,这一范围全失效(迭代器、指针和引用)。删除点之前的不受影响。
end()迭代器失效
deque
deque 不是一整块连续内存,而是多块定长缓冲区 + 一张“块索引表”(map)。
插入可能导致扩容(新分配一个连续内存段)。
迭代器里不仅有元素指针,还带着指向块及索引表的位置;一旦在两端扩展需要改动索引表,所有迭代器都会失效。但元素本身通常没搬家,所以引用/指针多数仍然有效(除非你删的就是它,或在中间插入/删除导致元素搬动)。这正是它与 vector/list 最大的差异。
- 插入
- 首尾插入
- 规定所有的迭代器失效(不包括指针、引用)。
- 引用/指针通常仍指向原元素,不失效!
- 无论是否扩容,其他的元素都是保留在原位置的,因此其他元素的引用/指针不受影响。
- 在中间插入
- 所有全失效(包括迭代器、指针和引用)。
- 首尾插入
- 删除
- 首尾元素
- 被删除元素的迭代器、指针和引用失效。其他元素不影响!
- 如果删除的是首元素,容器的end迭代器不失效(不包括指针、引用)。
- 只有这一种情况不使
end()失效,其他情况都不要用旧的end。- 但是,有可能虽然是pop_front,但恰好容器中只有一个元素,此时end也会失效。
- 只有这一种情况不使
- 如果删除的是尾元素,容器的end迭代器会失效(不包括指针、引用)。
- 删除中间元素
- 所有全失效(包括迭代器、指针和引用)。
- 首尾元素

list
- insert:不会让迭代器失效(所有元素,包括新插入的,都不会失效)。
- 但是,插入后,插入点放的是新元素,原来位置的元素被挤到了右边。如果需要继续向右遍历,记得在插入之后单独做一次
++。
- 但是,插入后,插入点放的是新元素,原来位置的元素被挤到了右边。如果需要继续向右遍历,记得在插入之后单独做一次
- erase:之后,仅对删除的元素的迭代器失效。其他仍有效。
map、multimap、set、multiset
- insert:无影响:不会让迭代器、指针、引用失效(所有元素,包括新插入的,都不会失效)。
- erase:仅对删除的元素的迭代器、指针、引用失效。其他元素仍有效。
unordered_map、unordered_set
哈希表的插入,可能会存在容器增长导致重新哈希。
插入后,新容器的尺寸超过其容量阈值(计算方式为容器的 bucket_count 乘以其 max_load_factor),则会强制执行重新哈希。删除不涉及重新哈希。
在重新哈希后,容器中的所有迭代器都会失效。(指针、引用仍有效,即使重新哈希)
- insert:
- 如果不涉及到重新哈希。不会让迭代器、指针、引用失效(所有元素,包括新插入的,都不会失效)。
- 如果重新哈希,容器中的所有迭代器失效。(但指针、引用仍有效,即使重新哈希)
- 元素的指针、引用在所有情况下都保持有效,即使在重新哈希之后也是如此。
- erase:仅对删除的元素的迭代器、指针、引用失效。其他元素仍有效。
其他如queue、stack、priority_queue
没有提供迭代器。不用谈失效的概念。
Array
- 固定大小;不会插/删;
- 修改元素值不使迭代器失效。
swap(array)不失效迭代器(指向同一块内存)。