在vector的迴圈中呼叫erase

2021-07-06 11:00:12 字數 1790 閱讀 4961

在使用

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

7

else

8

11     }
所要注意的是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,似乎有很多個版本的實現,而它們或多或少都有所偏差。這裡有兩個**,可以進行參考:和

最初犯了這樣的錯誤:

for(vector::iterator it=m_stgestureinfo.begin(); it != m_stgestureinfo.end(); /*it++*/)

pcurrtraj= pcurrtraj->getnext(); 

}if(false == bsameflag)

it = m_stgestureinfo.erase(it);

if(it == m_stgestureinfo.end()) //要控制迭代器不能超過整個容器  }

這樣導致,每次刪除後,刪除的後乙個元素不參與判斷。因為erase之後,後面的元素會移位,此時it指向另外刪除後面的元素,然後it++,最後會導致刪除後面的元素被跳過,因此

正確寫法:

for(vector::iterator it=m_stgestureinfo.begin(); it != m_stgestureinfo.end(); /*it++*/)

pcurrtraj= pcurrtraj->getnext();   

}if(false == bsameflag)

it = m_stgestureinfo.erase(it);

else

it++;

在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迴圈來處理。我們必須小...

js迴圈中呼叫ajax

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