C 迭代器失效的幾種情況總結

2022-05-05 08:00:10 字數 4162 閱讀 7546

一、序列式容器(陣列式容器)

對於序列式容器(如vector,deque),序列式容器就是陣列式容器,刪除當前的iterator會使後面所有元素的iterator都失效。這是因為vetor,deque使用了連續分配的記憶體,刪除乙個元素導致後面所有的元素會向前移動乙個位置。所以不能使用erase(iter++)的方式,還好erase方法可以返回下乙個有效的iterator。

1

for (iter = cont.begin(); iter !=cont.end();)

2

迭代器失效:

1

void

vectortest()28

9 vector::iterator iter;

10for (iter = container.begin(); iter != container.end(); iter++)

1115

16for (iter = container.begin(); iter != container.end(); iter++)

1720 }

報錯是:vectoriterator not incrementable.

迭代器在執行++操作時報錯!已經失效的迭代器不能再進行自增運算了。++**大致實現如下:

1 _myiter operator++(int)2

對於序列式容器,比如vector,刪除當前的iterator會使後面所有元素的iterator都失效。這是因為順序容器記憶體是連續分配(分配乙個陣列作為記憶體),刪除乙個元素導致後面所有的元素會向前移動乙個位置。(刪除了乙個元素,該元素後面的所有元素都要挪位置,所以,iter++,已經指向的是未知記憶體)。

但是erase方法可以返回下乙個有效的iterator。所以**做如下修改,就ok了。

1

void

vectortest()28

9 vector::iterator iter;

10for (iter = container.begin(); iter !=container.end();)

1115

else

1819}20

21for (iter = container.begin(); iter != container.end(); iter++)

2225 }

總結:vector是乙個順序容器,在記憶體中是一塊連續的記憶體,當刪除乙個元素後,記憶體中的資料會發生移動,以保證資料的緊湊。所以刪除乙個資料後,其他資料的位址發生了變化,之前獲取的迭代器根據原有的資訊就訪問不到正確的資料。

所以為了防止vector迭代器失效,常用如下方法:

1

for (iter = container.begin(); iter !=container.end(); )

28 }

這樣刪除後iter指向的元素後,返回的是下乙個元素的迭代器,這個迭代器是vector記憶體調整過後新的有效的迭代器。

二、關聯式容器

對於關聯容器(如map, set,multimap,multiset),刪除當前的iterator,僅僅會使當前的iterator失效,只要在erase時,遞增當前iterator即可。這是因為map之類的容器,使用了紅黑樹來實現,插入、刪除乙個結點不會對其他結點造成影響。erase迭代器只是被刪元素的迭代器失效,但是返回值為void,所以要採用erase(iter++)的方式刪除迭代器。

1

for (iter = cont.begin(); it !=cont.end();)29

10//

測試錯誤的map刪除元素

11void

maptest()

1227

28 cout<

map元素內容為:

"<

29 map::iterator iter;

30for (iter = datamap.begin(); iter != datamap.end(); iter++)

3136

37 cout<

內容開始刪除:

"<

38//

刪除操作引發迭代器失效

39for (iter = datamap.begin(); iter != datamap.end();iter++)

4049

/*cout

51 }

出錯:

解析:datamap.erase(iter)之後,iter就已經失效了,所以iter無法自增,即iter++就會出bug.解決方案,就是在iter失效之前,先自增。

1

void

maptest()217

18 cout<

map元素內容為:

"<

19 map::iterator iter;

20for (iter = datamap.begin(); iter != datamap.end(); iter++)

2126

27 cout<

內容開始刪除:

"<

28for (iter = datamap.begin(); iter !=datamap.end();)

2939

else42}

43 }

解析:datamap.erase(iter++);這句話分三步走,先把iter傳值到erase裡面,然後iter自增,然後執行erase,所以iter在失效前已經自增了。

map是關聯容器,以紅黑樹或者平衡二叉樹組織資料,雖然刪除了乙個元素,整棵樹也會調整,以符合紅黑樹或者二叉樹的規範,但是單個節點在記憶體中的位址沒有變化,變化的是各節點之間的指向關係。

所以在map中為了防止迭代器失效,在有刪除操作時,常用如下方法:

1

for (iter = datamap.begin(); iter !=datamap.end(); )

2else

1417 }

三、鍊錶式容器對於鍊錶式容器(如list),刪除當前的iterator,僅僅會使當前的iterator失效,這是因為list之類的容器,使用了鍊錶來實現,插入、刪除乙個結點不會對其他結點造成影響。只要在erase時,遞增當前iterator即可,並且erase方法可以返回下乙個有效的iterator。

方式一:遞增當前iterator

1

for (iter = cont.begin(); it !=cont.end();)

2

方式二:通過erase獲得下乙個有效的iterator

1

for (iter = cont.begin(); iter !=cont.end();)

2

四、總結迭代器失效分三種情況考慮,也是分三種資料結構考慮,分別為陣列型,鏈表型,樹型資料結構。

陣列型資料結構:該資料結構的元素是分配在連續的記憶體中,insert和erase操作,都會使得刪除點和插入點之後的元素挪位置,所以,插入點和刪除掉之後的迭代器全部失效,也就是說insert(*iter)(或erase(*iter)),然後在iter++,是沒有意義的。解決方法:erase(*iter)的返回值是下乙個有效迭代器的值。 iter =cont.erase(iter);

鏈表型資料結構:對於list型的資料結構,使用了不連續分配的記憶體,刪除運算使指向刪除位置的迭代器失效,但是不會失效其他迭代器.解決辦法兩種,erase(*iter)會返回下乙個有效迭代器的值,或者erase(iter++).

樹形資料結構:使用紅黑樹來儲存資料,插入不會使得任何迭代器失效;刪除運算使指向刪除位置的迭代器失效,但是不會失效其他迭代器.erase迭代器只是被刪元素的迭代器失效,但是返回值為void,所以要採用erase(iter++)的方式刪除迭代器。

注意:經過erase(iter)之後的迭代器完全失效,該迭代器iter不能參與任何運算,包括iter++,*ite

C 迭代器失效情況總結

迭代器失效分三種情況考慮,也是分三種資料結構考慮,分別為陣列型,鏈表型,樹型資料結構。陣列型資料結構 該資料結構的元素是分配在連續的記憶體中,insert和erase操作,都會使得刪除點和插入點之後的元素挪位置,所以,插入點和刪除掉之後的迭代器全部失效,也就是說insert iter 或erase ...

常見幾種stl迭代器失效情況總結

思前想後還是先多鞏固基礎在去學習新的技術為好,近期會整理一些對基礎知識的總結 迭代器失效是因為向容器插入或者刪除元素導致容器的空間變化或者說是次序發生了變化,使得原迭代器變得不可用。因此在對stl迭代器進行增刪操作時,要格外注意迭代器是否失效。下面介紹幾種常用的迭代器失效情況 list map se...

關於迭代器失效的幾種情況

一 序列式容器迭代器失效 1 順序容器 2 對於序列式容器vector deque 當當前元素iterator刪除後 就是刪除乙個元素後 從起始位置到當前刪除位置的迭代器是正常的,其後的所有元素的迭代器都會失效,這是因為vector deque都是連續的儲存一段空間,所以當對其進行erase操作時,...