在使用
vector
的過程中,有時會遇到需要迴圈遍歷
vector
,並刪除符合指定條件的元素。
當「指定條件」不複雜時,應該盡量使用
erase(remove_if(begin, end, func), end)
的形式來完成功能。
但有時候「指定條件」過於複雜,不得不顯式地寫乙個
for迴圈來處理。我們必須小心在意
erase
所帶來的
side effect
,乙個一般性的
for迴圈如下:
1for (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 與上面不同的是在每次呼叫...