迭代器是封裝了指標、過載了 -> 、* 、++等操作符的類模板,具有類似指標的行為。迭代器的設計是對資料結構的泛化,使不同容器具有相同的訪問方式,讓**不必依賴於特定的資料結構。指標也可以狹義的理解為迭代器。
在c++中經常使用迭代器對stl容器進行操作,但很多同學沒怎麼關注過迭代器失效的問題。迭代器失效,指迭代器指向錯誤的元素或無效的記憶體位址。要理解迭代器失效,首先要知道為什麼會造成迭代器失效。不同容器內部資料結構不一樣,插入、刪除容器中元素的操作會導致內部資料結構記憶體布局的改變,那麼就可能引起迭代器失效。所以理解迭代器失效,首先要了解容器的內部資料結構、以及該容器儲存新元素和刪除舊元素時的記憶體狀態。
根據容器內部的資料結構,我們可以將容器簡單分為:
標準stl序列容器:vector、string、dequeue、list內部資料結構:陣列(一段連續記憶體空間)標準stl關聯容器:set、multiset、map、multimap
插入操作:
1. 插入(push_back/insert)操作在vector中加入新的元素,但vector中元素總數仍不大於capacity,這時插入位置後的元素都被依次移動到下乙個位置,所以插入位置之後的迭代器都會失效。
2. 插入(push_back/insert)操作在vector中加入新的元素,但vector中元素總數大於capacity,這個時候會重新開闢更大的記憶體空間,將原來的vector中的內容複製到新的vector中,**原先vector的記憶體空間。由於新的vector的位址已完全改變,所以原先的所有迭代器都會失效。
刪除操作:刪除(pop_back/erase)操作在vector中刪除元素,刪除位置後的元素都被依次複製到前乙個位置,所以刪除位置之後的迭代器都會失效。
內部資料結構:陣列(多段連續記憶體空間,如圖所示)
插入操作:
1. 插入操作向deque 兩端 加入新元素時,如果這一端的分段陣列未滿,則直接加入,如果這一端的分段陣列已滿,只需建立新的分段陣列,並把該分段陣列的位址加入到索引陣列中即可。無論哪種情況都不需要對已有元素進行移動,故不會引起迭代器失效。
2. 插入操作向deque 中間 加入新元素時,需要將插入點到某一端之間的所有元素向容器的這一端移動,因此會使所有迭代器失效。
刪除操作:
1. 刪除操作在deque 兩端 刪除元素時,由於不需要移動元素,故只會使指向被刪除元素的迭代器失效。
2. 刪除操作在deque 中間 刪除元素時,需要將刪除點到某一端之間的所有元素都向刪除點移動,因此會使所有迭代器失效。
內部資料結構:雙向環狀鍊錶
插入操作:插入操作會申請新的節點空間,然後加入到鍊錶中,原來的迭代器指向的記憶體空間都未改變,故不會出現迭代器失效。
刪除操作:刪除操作只會引起被刪除節點的迭代器失效。
內部資料結構:紅黑樹
插入操作:插入操作會申請新的節點空間,然後加入都紅黑樹中,原來的迭代器指向的記憶體空間都未改變,故不會出現迭代器失效。
刪除操作:刪除操作只會引起被刪除節點的迭代器失效。
C STL 迭代器失效
2 刪除 當進行刪除操作 erase,pop back 後,指向刪除點的迭代器全部失效 指向刪除點後面的元素的迭代器也將全部失效。刪除點之前的迭代器仍有效。二 deque迭代器的失效情況 1 插入 1 在deque容器首部或者尾部插入元素不會使得任何迭代器失效。但是指向存在的元素的引用和指標不會失效...
C STL迭代器失效
迭代器失效就是說,對容器進行了一些操作後,先前的迭代器無法進行解引用操作去訪問容器的元素。迭代器失效可能會造成程式崩潰,如下圖 如果插入元素導致vector達到最大容量,那麼會重新分配記憶體並將老的元素拷貝到新的記憶體中。元素的位址都改變了,顯然迭代器和引用都將失效 如果插入元素沒有引起重新分配記憶...
C STL 迭代器失效問題
之前看 c primier 的時候,也解到在順序型視窗裡insert erase會涉及到迭代器失效的問題,並沒有深究。今天寫程式的時候遇到了這個問題。最初我的程式是醬紫的,別說話,我知道這樣是有問題的,可這樣是最直觀的想法 int arr vector int a arr,arr sizeof ar...