STL容器迭代器失效浅析
迭代器失效一般发生在对容器进行插入及删除操作时,插入/删除操作可能导致空间的重配置以及所指对象的位移而带来迭代器失效问题,我们可以归纳为以下两点:
- 由于容器元素整体“迁移”导致存放原容器元素的空间不再有效,从而使得指向原空间的迭代器失效。
- 由于删除元素使得某些元素次序发生变化使得原本指向某元素的迭代器不再指向希望指向的元素。
容器插入删除操作的迭代器情况
一般关联式容器的删除操作都会造成迭代器的失效下面通过几个序列容器的例子来简要分析以下迭代器失效的情况。
vector
vector是一个可以动态扩充的数组,它与array非常相似,不过随着新元素的加入它的内部机制会自行扩充空间以容纳新元素。
对于insert操作,若引起空间的重新分配即插入的元素无法被已有的容器容纳而造成的空间重分配时,原来的迭代器会指向无效的地址空间从而造成迭代器的失效。
对于erase操作,由于删除元素而带来的元素向前迁移,会导致当前迭代器及以后所有的迭代器失效。
list
list是一个双向链表,插入和删除都能在O(1)时间内完成,不会造成空间的重新配置或是数据的大规模迁移。
对于insert操作,所有迭代器均不会失效。
对于erase操作,当前迭代器会由于节点的删除而失效,其他迭代器均不会失效。
deque
deque是一种双向开口的连续线性空间,它允许常数时间内对头端进行元素的插入或删除操作。他不想vector那样占用一大片连续的线性空间,它是动态的以分段连续空间组合而成。
deque的迭代器相比上面两种是相对复杂的它首先应能够指出当前所在节点,以及所在节点中缓冲区的位置。
对于insert操作,deque的插入操作有push_back/push_front/insert增加任何元素都将使deque的迭代器失效,从STL的源码中可以看出,无论是哪种方式的插入操作,迭代器都会被调整从而导致迭代器失效。
对于erase操作,在deque的中间删除元素将使迭代器失效。在deque的头或尾删除元素时,只有指向该元素的迭代器失效。在删除两端的元素时,由于删除完毕后迭代器的调整,迭代器不会失效,而若删除中间节点的元素,当前的迭代器会失效。