對於序列式容器(如vector,deque),刪除當前的iterator會使後面所有元素的iterator都失效。這是因為vetor,deque使用了連續分配的記憶體,刪除乙個元素導致後面所有的元素會向前移動乙個位置。所以不能使用erase(iter++)的方式,還好erase方法可以返回下乙個有效的iterator。
序列容器,在記憶體中是一塊連續的記憶體,當刪除乙個元素後,記憶體中的資料會發生移動,以保證資料的緊湊。所以刪除乙個資料後,其他資料的位址發生了變化,之前獲取的迭代器根據原有的資訊就訪問不到正確的資料。
為了防止迭代器失效,刪除常用如下方法:
for (iter = container.begin(); iter != container.end(); )
}
這樣刪除後iter指向的元素後,返回的是下乙個有效元素的迭代器,這個迭代器是vector記憶體調整過後新的有效的迭代器。萬無一失!
以vector為例分析:
引起記憶體重新分配的插入運算使所有迭代器失效,插入也使得插入位置及其後位置的迭代器失效,刪除運算使得刪除位置及其後位置的迭代器失效.
vector的push_back操作 可能沒事。但是一旦引發記憶體重分配,所有迭代器都會失效,此時所有儲存位置被重新分配。
vector的insert操作 插入點之後的所有迭代器失效;但一旦引發記憶體重分配,所有迭代器都會失效;但其返回前乙個有效迭代器
vector的erase操作 插入點之後的所有迭代器失效;返回後乙個有效迭代器
vector的reserve操作 所有迭代器失效(因為它導致記憶體重分配);
對於deque:
deque 的儲存方式是「分塊雙向鍊錶」的結構,塊內是連續的線性表,塊間是雙向鍊錶。形象點的說就是,deque是乙個由指標組成的陣列(當然,那不是陣列,而是一小塊連續空間,在deque中稱這塊連續空間為map),其中的指標再指向另一段(較大的)連續線性空間,稱為緩衝區,緩衝區才是deque儲存空間的主體,裡面存放的是真正的元素。
對於插入操作:
插入工作引起deque記憶體重新分配的情況也會出現,但是那不是針對deque迭代器來說的,而對於deque中的map來說。deque只是將map的節點,從舊的空間複製到新的map中,但是其中作為儲存實體的緩衝區沒有重新分配,所以指向這些緩衝區的迭代器並沒有失效。
deque容器的任何其他位置的插入和刪除操作將使指向該容器元素的所有迭代器失效,只會是那個元素所在的塊的迭代器失效(這個失效的原因與 vector 類似)
,但是我們沒辦法那些塊有多大,也就沒辦法判斷到底哪些迭代器失效了,所以必須重新獲取。插入和刪除操作會引起插入點之前或者之後的元素進行移動(呼叫copy函式)。除了首尾的插入(完全不失
效)和刪除(僅僅當前迭代器失效)。
對於關聯容器(如map, set, multimap,multiset),刪除當前的iterator,僅僅會使當前的iterator失效,只要在erase時,遞增當前iterator即可。這是因為map之類的容器,使用了紅黑樹來實現,插入、刪除乙個結點不會對其他結點造成影響。整棵樹也會調整,以符合紅黑樹或者二叉樹的規範,但是單個節點在記憶體中的位址沒有變化,變化的是各節點之間的指向關係。
erase操作後,迭代器只是被刪元素的迭代器失效,但是返回值為void,所以要採用erase(iter++)的方式刪除迭代器。
void maptest()
cout<<"map元素內容為:"<::iterator iter=datamap.begin(),temp=null;
for (; iter != datamap.end(); iter++)
coutif (key% 2 == 0)
datamap.erase(iter++);//或者 temp=iter;iter++;erase(temp)
else{
coutlist也存在迭代器失效的問題,不同的是,以上兩種方式,都適合list. 因為對於list來說,它使用了不連續分配的記憶體,並且它的erase方法也會返回下乙個有效的iterator,因此上面兩種方法都可以使用。list實際使用鍊錶儲存資料。
list適用於包含大量刪除和插入操作的資料結構。
迭代器失效 典型的迭代器失效
首先對於vector而言,新增和刪除操作可能使容器的部分或者全部迭代器失效。那為什麼迭代器會失效呢?vector元素在記憶體中是順序儲存,試想 如果當前容器中已經存在了10個元素,現在又要新增乙個元素到容器中,但是記憶體中緊跟在這10個元素後面沒有乙個空閒空間,而vector的元素必須順序儲存一邊索...
迭代器失效
迭代器 iterator 是乙個可以對其執行類似指標的操作 如 解除引用 operator 和遞增 operator 的物件,我們可以將它理解成為乙個指標。但它又不是我們所謂普通的指標,我們可以稱之為廣義指標,你可以通過sizeof vector iterator 來檢視,所佔記憶體並不是4個位元組...
迭代器失效
在stl容器中,經常會出現迭代器失效導致程式執行時崩潰,那迭代器究竟是如何失效的呢?迭代器 iterator 是乙個可以對其執行類似指標的操作 如 解除引用 operator 和遞增 operator 的物件,我們可以將它理解成為乙個指標。但它又不是我們所謂普通的指標,我們可以稱之為廣義指標,你可以...