1. 程式人生 > >關於迭代器失效

關於迭代器失效

(前置技能)關於++i和i++

i++的過程:先拷貝一份原始值至另外的記憶體地址中,然後這份被拷貝的原始值應用於後續的計算過程中,然後自身加1;
++i的過程:先自增,然後把自增後的值拷貝一份到另外的記憶體地址中,這份被拷貝的值應用於後續計算。

內建資料型別的情況,效率沒有區別。
自定義資料型別的情況,++i效率較高。

set,map的迭代器失效

typedef map<int, int> Map;
typedef map<int, int>::iterator MapIt;

Map m;
MapIt it;
for(it = m.begin
(); it != m.end(); /*不能再自增了,不能i++*/){ //因為對於關聯的容器map來說, m.erase(it);後,it就失效了 if(*it%2 == 0) m.erase(it++);//這個原理看上面i++ else it++; //或者 if(*it%2 == 0) it = m.erase(it);//通過erase方法的返回值來獲取下一個有效迭代器 else it++; }

vector,deque的迭代器失效

//序列式容器,使用了連續分配的記憶體,刪除一個元素導致後面所有的元素會向前移動一個位置。

vector<int> v;
for(vector<int>::iterator it = v.begin(); it != v.end(); /*不能再自增了*/){ it = v.erase(it); // 刪除當前的iterator,後面的vector元素自動向前挪動,後面的迭代器全部會失效(關聯的map容器元素不會自動挪動), 所以不能再把it進行++ }

觸發各容器迭代器失效的情況

list

內部資料結構:雙向環狀連結串列。
使用了不連續分配的記憶體,它的erase方法也會返回下一個有效的iterator,因此上面兩種迭代方法都可以使用。

增加任何元素都不會使迭代器失效。刪除元素時,除了指向當前被刪除元素的迭代器外,其它迭代器都不會失效。

vector

內部資料結構:陣列。

vector的迭代器在記憶體重新分配時將失效 或
指向當前元素以後的任何元素的迭代器都將失效。
(直接在後面增加一塊記憶體和重新分配記憶體分別對應這兩種情況)

當刪除元素時,指向被刪除元素以後的任何元素的迭代器都將失效。
(因為資料結構是陣列,明顯知道刪除後會使後面所有元素改變,所以刪除O(n)也可以證明)

stack, queue

一般使用deque作為支援的序列容器。
不能遍歷。。

map, set

關聯式容器:使用了紅黑樹來實現,插入、刪除一個結點不會對其他結點造成影響。
如果迭代器所指向的元素被刪除,則該迭代器失效。其它任何增加、刪除元素的操作都不會使迭代器失效

deque

增加任何元素都將使deque的迭代器失效。在deque的中間刪除元素將使迭代器失效。在deque的頭或尾刪除元素時,只有指向該元素的迭代器失效。