最近在專案開發中,遇到乙個異常,經過測試,發現是迭代器失效問題,於是稍微總結了一下。
vector迭代器失效測試:
測試程式:
void vectortest()
vector<
int>::iterator iter;
for (iter = container.begin(); iter != container.end(); iter++)
for (iter = container.begin(); iter != container.end(); iter++)
vector<
int>::iterator iter;
for (iter = container.begin(); iter != container.end(); )
} for (iter = container.begin(); iter != container.end(); iter++)
cout<<
"map元素內容為:
"string>::iterator iter;
for (iter = datamap.begin(); iter != datamap.end(); iter++)
cout
結果報錯:
看看報異常時跟進去在**報錯:
根據迭代器訪問資料時失效! map/set iterator not dereferencable
迭代器是不引用的。
正確的做法是:
void maptest()
cout<<
"map元素內容為:
"string>::iterator iter;
for (iter = datamap.begin(); iter != datamap.end(); iter++)
else
if (iter != datamap.end())
cout
最後輸出結果:
程式在一邊刪除一遍輸出,而且能夠順利輸出結束。
總結一下:
vector是乙個順序容器,在記憶體中是一塊連續的記憶體,當刪除乙個元素後,記憶體中的資料會發生移動,以保證資料的緊湊。所以刪除乙個資料後,其他資料的位址發生了變化,之前獲取的迭代器根據原有的資訊就訪問不到正確的資料。
所以為了防止vector迭代器失效,常用如下方法:
for (iter = container.begin(); iter != container.end(); )
}
這樣刪除後iter指向的元素後,返回的是下乙個元素的迭代器,這個迭代器是vector記憶體調整過後新的有效的迭代器。萬無一失!
map是關聯容器,以紅黑樹或者平衡二叉樹組織資料,雖然刪除了乙個元素,整棵樹也會調整,以符合紅黑樹或者二叉樹的規範,但是單個節點在記憶體中的位址沒有變化,變化的是各節點之間的指向關係。
所以在map中為了防止迭代器失效,在有刪除操作時,常用如下方法:
for (iter = datamap.begin(); iter != datamap.end(); )
else }
其中,
map::iterator tmpiter = iter; iter++;
datamap.erase(tmpiter);
這幾句的意思是,先保留要刪除的節點迭代器,再讓
iter
向下乙個有意義的節點,然後刪除節點。
所以這個操作結束後iter指向的是下乙個有意義的節點,沒有失效。
其實這三句話可以用在一句話代替,就是datamap.erase(iter++);
解釋是先讓iter指向下乙個有效的節點,但是返回給erase函式的是原來的iter副本。這個可能跟++這個操作的本身語法相關。
但是功能跟上面是一樣的。
STL容器迭代器失效問題
眾所周知當使用乙個容器的insert或者erase函式通過迭代器插入或刪除元素 可能 會導致迭代器失效,因此很多建議都是讓我們獲取insert或者erase返回的迭代器,以便用重新獲取新的有效的迭代器進行正確的操作 view plaincopy to clipboardprint?iter vec....
STL迭代器失效的問題
內部資料結構 連續儲存,例如陣列。隨機訪問每個元素,所需要的時間為常量。在末尾增加或刪除元素所需時間與元素數目無關,在中間或開頭增加或刪除元素所需時間隨元素數目呈線性變化。可動態增加或減少元素,記憶體管理自動完成,但程式設計師可以使用reserve 成員函式來管理記憶體。迭代器失效 插入 vecto...
STL容器迭代器失效問題
眾所周知當使用乙個容器的insert或者erase函式通過迭代器插入或刪除元素 可能 會導致迭代器失效,因此很多建議都是讓我們獲取insert或者erase返回的迭代器,以便用重新獲取新的有效的迭代器進行正確的操作 view plaincopy to clipboardprint?iter vec....