C STL迭代器失效

2021-10-23 22:51:26 字數 1689 閱讀 4643

迭代器失效就是說,對容器進行了一些操作後,先前的迭代器無法進行解引用操作去訪問容器的元素。迭代器失效可能會造成程式崩潰,如下圖

如果插入元素導致vector達到最大容量,那麼會重新分配記憶體並將老的元素拷貝到新的記憶體中。元素的位址都改變了,顯然迭代器和引用都將失效;

如果插入元素沒有引起重新分配記憶體,那插入元素的前面元素的迭代器和引用依然有效,但是插入元素以及它之後的所有元素的迭代器和引用將失效。因為它們往後挪了乙個位置,位址發生了改變。

刪除元素的前面元素的迭代器和引用依然有效,但是後面元素的迭代器和引用將失效。因為它們往前挪了乙個位置,位址發生了改變。

deque由於內部結構的複雜,迭代器失效的場景也會有些複雜。先看一下deque的內部大體實現:

deque會將新加入的元素加入到資料塊裡,如果當前的資料塊滿了,就會再申請乙個資料塊並將新元素插入到新資料塊裡。deque內部還有乙個資料塊指標陣列,裡面存放了指向這些資料塊的指標。要想通過迭代器訪問deque中的元素,首先迭代器需要包含乙個指標指向資料塊指標陣列某個單元來訪問資料塊,其次還需要包含乙個指標指向資料塊裡所要訪問元素所在的具體位置。

下面具體分析deque迭代器失效的場景:

在隊首或隊尾插入元素,所有元素的迭代器都將失效,引用仍然有效。這點不太好理解,查閱了網上很多解釋,有一種說法比較合理:

在隊首或隊尾插入元素,資料塊裡的其他元素不會發生挪動,所以其他元素的位址不變,引用仍然有效。但是如果插入時資料塊已滿,那麼就要重新申請資料塊。有了新的資料塊,那當然也要新加乙個指標指向它,並新增到資料塊指標陣列。而資料塊指標陣列也是有最大容量的,如果這個陣列已達到最大容量,那麼就會回到vector達到最大容量時的場景,重新申請一塊更大的記憶體,把老的指標全部拷貝到新的記憶體裡。那麼顯然,所有元素的迭代器裡存放的資料塊指標還指向老的非法位址,迭代器也就變成失效了。

在中間位置插入元素,所有元素的迭代器和引用都將失效。這個應該是所有元素挪動引起的。

刪除隊首或隊尾元素,除被刪的元素外,其他元素的迭代器和引用都依然有效;

刪除中間元素,所有元素的迭代器和引用都將失效。

插入元素不會影響其他元素的迭代器。因為list使用了不連續分配的記憶體。

除當前被刪的元素,其他元素迭代器依然有效。

同list

如果插入元素後,容器的大小超過了它的最大容量,就會觸發rehash,導致所有元素的迭代器失效,但是引用依然有效。

除被刪的元素外,其他元素的迭代器依然有效。

經過erase(iter)之後的迭代器完全失效,該迭代器iter不能參與任何運算,包括iter++,*ite。erase的返回值通常是刪除元素的下乙個元素的迭代器,可以通過返回值避免操作失效的迭代器引發程式崩潰。

for

(auto iterator = container.

begin()

; iterator != container.

end();

)

參考資料:

1.2.

3.4.

5.

C STL 迭代器失效

2 刪除 當進行刪除操作 erase,pop back 後,指向刪除點的迭代器全部失效 指向刪除點後面的元素的迭代器也將全部失效。刪除點之前的迭代器仍有效。二 deque迭代器的失效情況 1 插入 1 在deque容器首部或者尾部插入元素不會使得任何迭代器失效。但是指向存在的元素的引用和指標不會失效...

C STL 迭代器失效問題

之前看 c primier 的時候,也解到在順序型視窗裡insert erase會涉及到迭代器失效的問題,並沒有深究。今天寫程式的時候遇到了這個問題。最初我的程式是醬紫的,別說話,我知道這樣是有問題的,可這樣是最直觀的想法 int arr vector int a arr,arr sizeof ar...

C STL容器迭代器失效 筆記

迭代器是封裝了指標 過載了 等操作符的類模板,具有類似指標的行為。迭代器的設計是對資料結構的泛化,使不同容器具有相同的訪問方式,讓 不必依賴於特定的資料結構。指標也可以狹義的理解為迭代器。在c 中經常使用迭代器對stl容器進行操作,但很多同學沒怎麼關注過迭代器失效的問題。迭代器失效,指迭代器指向錯誤...