大致內容來源:http://blog.csdn.net/lujiandong1/article/details/49872763數組
1.對於序列式容器:vector,queue等,序列式容器就是數組式容器,刪除當前的iterator會使得後邊全部元素的iterator都失效。這是由於其使用了連續分配的內存,闡述一個元素致使後面全部的元素都會向前移動一個位置,因此不能使用erase(iter++)的方式。可是erase方法能夠返回下一個有效的iteratorfor (iter = cont.begin(); iter != cont.end();) { (*it)->doSomething(); if (shouldDelete(*iter)) iter = cont.erase(iter); //erase刪除元素,返回下一個迭代器 else ++iter; }
迭代器失效的狀況:數據結構
void vectorTest() { vector<int> container; for (int i = 0; i < 10; i++) { container.push_back(i); } vector<int>::iterator iter; for (iter = container.begin(); iter != container.end(); iter++) { if (*iter > 3) container.erase(iter); } for (iter = container.begin(); iter != container.end(); iter++) { cout<<*iter<<endl; } }
這段代碼在刪除後對迭代器自增,實際其自己已經失效了。 對於vector,刪除當前的iterator會使得用棉全部元素的iterator都失效,由於序列式容器內存是連續分配的,刪除一個元素致使後面全部的元素都會向前移動一個位置。spa
因此此時iter++指向的未知位置。正確的作法是向前面同樣的處理。.net
對於關聯式容器如(map,set,multimap,multiset),刪除當前的iterator,僅僅會使當前的iterator失效,只要在erase時,遞增當前iterator便可。這是由於map之類的容器,使用了紅黑樹來實現,插入、刪除一個節點不會對其餘節點形成影響,erase迭代器只是被刪元素的迭代器失效,可是返回值爲void,因此要採用erase(iter++)的方式刪除迭代器。code
void mapTest() { map<int, string> dataMap; for (int i = 0; i < 100; i++) { string strValue = "Hello, World"; stringstream ss; ss<<i; string tmpStrCount; ss>>tmpStrCount; strValue += tmpStrCount; dataMap.insert(make_pair(i, strValue)); } cout<<"MAP元素內容爲:"<<endl; map<int, string>::iterator iter; for (iter = dataMap.begin(); iter != dataMap.end(); iter++) { int nKey = iter->first; string strValue = iter->second; cout<<strValue<<endl; } cout<<"內容開始刪除:"<<endl; /////////////////////////////////////////////擦除操做引起迭代器失效 for (iter = dataMap.begin(); iter != dataMap.end();iter++) { int nKey = iter->first; string strValue = iter->second; if (nKey % 2 == 0) { dataMap.erase(iter); } /* cout<<iter->second<<endl;*/ } }
上述代碼會出現問題:dataMap.erase(iter)以後,iterator就已經失效了,因此iter沒法自增,解決的辦法就是在其失效以前完成自增。blog
作出以下修改內存
for (iter = dataMap.begin(); iter != dataMap.end();) { int nKey = iter->first; string strValue = iter->second; if (nKey % 2 == 0) { dataMap.erase(iter++); auto a = iter; } else { iter ++; } }
解析:dataMap.erase(iter++);這句話分幾步走,先把iter傳到erase裏面,而後iter自增,而後再erase,因此iter在失效前已經自增了。string
map是關聯式容器,以紅黑樹或者平衡二叉樹組織數據,雖然刪除了一個元素,整棵樹也會調整,以符合二叉樹或者紅黑樹的規範,可是單個節點的改變必然會調整樹的結構,其中單個節點在內存中的地址沒有變化且各個節點的指向關係。另一種保險和比較易讀的寫法是寫一個臨時迭代器保存當前迭代器,以後迭代器自己自增,在erase臨時的it
代碼以下:class
if (nKey % 2 == 0) { map<int, string>::iterator tmpIter = iter; iter++; dataMap.erase(tmpIter); //dataMap.erase(iter++) 這樣也行 }
總結:迭代器的失效分三種狀況,分爲數組形,鏈表性,樹形數據結構
數組形數據結構:該數據結構元素是分配在連續的內存中。
鏈表性數據結構:其也是用了不連續分配的內存
樹形數據結構:插入不會使得任何迭代器失效。