一、引言
迭代器是一种面向对象的广义指针,用于指向容器中或流中的对象。
迭代器是一种设计模式,它提供了一种方法来访问容器(例如数组、列表、集合等)中的元素。迭代器是一个对象,它包含了容器中元素的引用,以及一个指向容器中下一个元素的指针。
迭代器可以用来遍历容器中的元素,也可以用于搜索和排序等操作。迭代器的优势在于它可以延迟计算,只有在需要时才会计算下一个元素,这样可以节省内存和计算资源。
二、什么是迭代器失效
指的是一种由特定操作引发的现象,这些特定操作对容器进行操作,使得迭代器不指向容器内的任何元素,或者使得迭代器指向的容器元素发生了改变
三、序列式容器引起迭代器失效
vector
push_back,如果有剩余空间,没有引起扩容,则end迭代器会失效;如果引起扩容,则全部迭代器都失效
pop_back,end迭代器会失效
insert,如果未引起扩容,则插入点及插入点之后的迭代器都失效;如果引起扩容,则全部迭代器都失效
erase,插入点及插入点之后的迭代器都失效。
resize,如果扩容,则会迭代器全部失效。如果不扩容反而缩小,则缩小导致消失的元素的迭代器都失效
(swap操作不会引起迭代器失效)
clear :影响size, 但是指向clear执行前的所有元素的迭代器均未失效,只是逻辑删除
list
list是双向循环链表,很多操作都是操作指针,也没有扩容,所以相对迭代器失效的范围较小
push_back():原迭代器中end()会失效,其他的都不会失效。
push_front():原迭代器中begin()会失效,其他的都不会失效。
pop_back():原迭代器中end()会失效,其他的都不会失效
pop_front():原迭代器中begin()会失效,其他的都不会失效。
insert(iterator, n):原迭代器中插入点会失效,其他的都不会失效。
erase(iterator):原迭代器中删除点会失效,其他的都不会失效。
deque
push_back():会直接在容器末尾添加一个元素。原迭代器中end()会失效,其他的都不会失效。
push_front():会直接在容器头部添加一个元素。原迭代器中begin()会失效,其他的都不会失效。
pop_back():会直接删除最后一个元素。原迭代器中end()会失效,其他的都不会失效
pop_front():会直接在容器头部删除一个元素。原迭代器中begin()会失效,其他的都不会失效。
insert(iterator, n):向前移动则导致原迭代器中插入点及插入点之前的迭代器都失效;向后移动则导致迭代器中插入点及插入点之后的迭代器都失效。
erase(iterator):向前移动将导致原迭代器中删除点及删除点之后的迭代器失效;向后移动将导致原迭代器中删除点及删除点之前的迭代器都失效。
set、multiset、map、multimap
关联容器的底层结构为红黑树,都是节点。所有操作同list一样,都只是移动指针,进行节点调整,但是每个节点在内存的位置都是不变的。各成员函数导致的迭代器失效问题同list。
unordered_map unordered_set
若插入引起rehash,则所有迭代器失效。若不rehash,依然有效。
在C++中,unordered_set是一个基于哈希表实现的容器。当插入或删除元素时,unordered_set可能会自动重新分配内存并重新哈希元素。如果重新哈希后的元素数量发生变化,那么原来指向旧元素的迭代器就会失效。但是,如果不需要遍历所有元素,可以使用unordered_set的成员函数begin()和end()来获取迭代器的起始和结束位置,从而避免迭代器失效的问题。