STL 容器迭代器失效總結
本文只總結常見的序列容器(vector、deque、list)和關聯容器(set、multiset、map、multimap)的迭代器失效問題。
原迭代器指的是進行操作之前儲存的迭代器,包括begin()、end()以及其他位置的迭代器。
vector:
成員函式push_back():會在容器末尾新增一個元素。如果容器有剩餘空間(capacity() > size()),則直接新增新元素到容器尾部。此時,原迭代器中end()會失效,其他的都不會失效。否則,會導致容器重新分配記憶體,然後將資料從原記憶體複製到新記憶體,再在尾部新增新元素。此時,由於記憶體重新分配,原迭代器(所有)都失效。
成員函式pop_back():直接將容器中的最後一個元素刪除,原迭代器中end()會失效,其餘的都不會失效。
成員函式insert(iterator, n):如果容器有剩餘空間,先在容器尾部插入一個元素,然後將插入點及之後的元素都向後移動一位,然後在插入點建立新元素。否則,會導致容器重新分配記憶體,接著將插入點之前的元素複製過去,在插入點建立新元素,再將插入點之後的元素複製過去。因此,如果沒有記憶體的重新分配,原迭代器中插入點及插入點之後的迭代器(包括end())都失效。如果有記憶體的重新分配,原迭代器(所有)都失效。
成員函式erase(iterator):將刪除點及之後的元素都向前移動一位,然後刪除最後一個元素。因此,原迭代器中刪除點之前的迭代器都有效,插入點及插入點之後的迭代器都失效。
deque:
成員函式push_back():會直接在容器末尾新增一個元素。原迭代器中end()會失效,其他的都不會失效。
成員函式push_front():會直接在容器頭部新增一個元素。原迭代器中begin()會失效,其他的都不會失效。
成員函式pop_back():會直接刪除最後一個元素。原迭代器中end()會失效,其他的都不會失效
成員函式pop_front():會直接在容器頭部刪除一個元素。原迭代器中begin()會失效,其他的都不會失效。
成員函式insert(iterator, n):如果插入點之前的元素較少,會在容器頭部插入一個元素,然後將插入點及其之前的所有元素向前移動一位,再在插入點建立新元素。否則,將插入點及其之後的元素向後移動一位,再在插入點建立新元素。因此,向前移動則導致原迭代器中插入點及插入點之前的迭代器都失效;向後移動則導致迭代器中插入點及插入點之後的迭代器都失效。
成員函式erase(iterator):如果刪除點之前的元素較少,將刪除點之前的所有元素向後移動一位,再刪除第一個元素。否則,將刪除點之後的所有元素向前移動一位,再刪除最後一個元素。因此,向前移動將導致原迭代器中刪除點及刪除點之後的迭代器失效;向後移動將導致原迭代器中刪除點及刪除點之前的迭代器都失效。
list:
因為list的底層結構是雙向連結串列,所有操作都只是針對節點移動指標,不會涉及到位置變化,操作影響的範圍很小。
成員函式push_back():原迭代器中end()會失效,其他的都不會失效。
成員函式push_front():原迭代器中begin()會失效,其他的都不會失效。
成員函式pop_back():原迭代器中end()會失效,其他的都不會失效
成員函式pop_front():原迭代器中begin()會失效,其他的都不會失效。
成員函式insert(iterator, n):原迭代器中插入點會失效,其他的都不會失效。
成員函式erase(iterator):原迭代器中刪除點會失效,其他的都不會失效。
set、multiset、map、multimap
關聯容器的底層結構為紅黑樹,所有操作同list一樣,都只是移動指標,各成員函式導致的迭代器失效問題同list。
注意:文中成員函式的內部實現以SGI STL為準。