std::vector<int> v;
v.push_back(0);
std::vector<int>::iterator vi = v.begin();
while(vi != v.end())
{
if(*vi == 0)
{
v.erase(vi++);
continue;
}
++vi;
}
以上這段code在VC2003上run是正常的, 用gcc 3.2.2的話會造成segmentation fault。
正確的寫法應該是 vi = v.erase(vi);
Simple is beautiful
std::vector<int> v;
v.push_back(0);
std::vector<int>::iterator vi = v.begin();
while(vi != v.end())
{
if(*vi == 0)
{
v.erase(vi++);
continue;
}
++vi;
}
4 則留言:
hi, code 的第二行應該是 "v.push_back(0);" :)
感謝指正
在 gcc 與 msvc 都是先 vi++ 而後 v.erase().
先不考慮根據 C++ 標準, 對 vector 做 erase/insert 等會使所有的 iterator 失效...
在第一次 vi++ 後, vi 實際上已經等於此刻的 v.end(), 但傳遞給 v.erase() 的 iterator 仍是 vi 原本的值 (increment 之前的值, 因為是 postfix increment).
而當 v.erase() 執行後. v.end() 在這時候被往前移動了一步. 也就是說 vi 的位置超過了新的 v.end() 變成無效的 iterator 永遠不會等於 v.end(). 於是接下來的都成為 undefined behavior.
你可以把那一行 vi.erase(vi++) 改成等校的三個 statement: iterator pos = vi; ++vi; vi.erase(pos); 也會得到同樣的結果.
我手上沒有 vc2003, 因此無法得知為什麼這個程式不會馬上出錯. 用 2005 測試的結果也是會出錯, 雖然錯誤的時間與地點不同, 但也不讓人意外, 畢竟是 undefined behavior.
很顯然你已經知道正確的作法 vi = v.erase(vi). 但分析問的的推論還不是正確的. 加油~
嗯 原來重點是end()這個iterator會移位
難怪我在刪除非最後一個元素的時候, 都不會發生錯誤
當初因為已經知道正確寫法, 所以就沒去深究了...
真是受教了:P
張貼留言