在vector的迴圈中呼叫erase

2022-07-03 12:42:12 字數 1515 閱讀 9499

在使用

vector

的過程中,有時會遇到需要迴圈遍歷

vector

,並刪除符合指定條件的元素。

當「指定條件」不複雜時,應該盡量使用

erase(remove_if(begin, end, func), end)

的形式來完成功能。

但有時候「指定條件」過於複雜,不得不顯式地寫乙個

for迴圈來處理。我們必須小心在意

erase

所帶來的

side effect

,乙個一般性的

for迴圈如下:

1

for (std::vector::iterator it = intvec.begin(); it != intvec.end(); /**/)2

7else

811 }

所要注意的是

it = intvec.erase(it)

。實際上這裡如果寫成

intvec.erase(it)

,即不對

it做重新賦值,**也能正常執行,特別是

release

版本幾乎所有的編譯器編譯後都能產生結果正確的**。而

debug

模式下有一些較新的編譯器會在編譯時給出警告,並在執行時出現斷言錯誤。

為什麼乙個錯誤的寫法在大多數情況下都能得到正確的答案?

根據stl

的描述,執行

erase(it)

後,it和it

之後的迭代器都可能會失效。這一點很好理解。因為

vector

一般由動態陣列實現,它的元素在記憶體中是連續儲存的。當刪除掉

it所指向元素時,原本在

it後面的元素需要集體前移。迭代器本身幾乎可以理解為是乙個指標,在

erase

之後它所指向的位置並沒有變化,只是那個位置的元素發生了變化,而且恰好變成了我們所想要的。至少大多數

stl版本是這麼實現的,因為這處理起來比較自然。

然而我們不能依賴於這個一般性事實,而應該採用

it=intvec.erase(it)

的形式來對

it重新賦值。

stl中有要求

vector

的erase

函式要返回指向被

erase

的迭代器的下乙個位置

,寫成it=intvec.erase(it)

是萬無一失的,而寫成

intvec.erase(it)

雖然實際可行,但是具有潛在風險,萬一某一天

erase

會影響it

的指向(

stl只要求

erase

移除元素,而沒***

it自身不變),程式就極有可能出問題。

根據標準所描述的約束來程式設計,而不是根據具體的實現細節來程式設計。

對於c++ stl

,似乎有很多個版本的實現,而它們或多或少都有所偏差。這裡有兩個**,可以進行參考:和。

在vector的迴圈中呼叫erase

在使用vector的過程中,有時會遇到需要迴圈遍歷vector,並刪除符合指定條件的元素。當 指定條件 不複雜時,應該盡量使用erase remove if begin,end,func end 的形式來完成功能。但有時候 指定條件 過於複雜,不得不顯式地寫乙個for迴圈來處理。我們必須小心在意er...

在vector的迴圈中呼叫erase

在使用 vector的過程中,有時會遇到需要迴圈遍歷vector,並刪除符合指定條件的元素。當 指定條件 不複雜時,應該盡量使用erase remove if begin,end,func end 的形式來完成功能。但有時候 指定條件 過於複雜,不得不顯式地寫乙個for迴圈來處理。我們必須小心在意e...

js迴圈中呼叫ajax

var i for i 0 i 10 i 在for迴圈中呼叫ajax方法 補充頁面上的資料,這樣寫是錯誤的,他不會每執行一次for迴圈就執行一次ajax方法,而是等for迴圈結束才去執行ajax方法,所以導致ajax只被執行一次。然而當修改如下 for i 0 i 10 i 與上面不同的是在每次呼叫...