2010-10-05 68 views
1

可能重複:
Can you remove elements from a std::list while iterating through it?STL列表中刪除項目

我想從列表中刪除項目,而迭代。我之前做過這個,但不知怎的,這個簡單的例子讓我失望了。 thnx提前幫助!

#include<iostream> 
#include<list> 
using namespace std; 

void main() 
{ 
    list<int> x; 
    for (int i =0;i<10; i++) 
     x.push_back(i); 

    for(list<int>::iterator k = x.begin(); k != x.end();k++) 
     cout<<*k<<" "; 

    cout<<endl; 

    for(list<int>::iterator k = x.begin(); k != x.end();k++) 
    { 
     if ((*k)%2) 
     { 
      x.erase(k); 
     } 
    } 

    cout<<endl; 
    getchar(); 
} 

回答

5

erase擦除元素之後返回元素:http://www.cplusplus.com/reference/stl/vector/erase/

因此,嘗試這樣的事:

for(list<int>::iterator k = x.begin(); k != x.end();) 
    if((*k)%2)   
    k=x.erase(k); 
    else 
    ++k; 
+0

2人輕傷尼特)K ++是更好的那++ K(作爲一種習慣)。特別是複雜的類型(按照Scott Myers)。 B)我總是評論爲什麼我離開了在增量爲 – pm100 2010-10-05 18:48:20

+0

@ PM100「K ++是更好的那++ K(作爲一種習慣)」 - 我認爲這是真的打碼機偏好,除非你正在處理的副作用的問題。但是就其本身而言,++ k或k ++都可以。我其實更喜歡第一種方式。 – dcp 2010-10-05 18:51:29

+1

@dcp:在特定的迭代器其實是可以有PERF的影響,因爲後綴版本實際上有做迭代器的副本,以及一些迭代器是「胖」,以至於編譯器不能充分優化是走內聯後。在這種特殊情況下,它很可能會發生,但是正如pm100所說,作爲_habit_,使用迭代器是很好的選擇。 – 2010-10-05 18:59:34

0

當您這樣做時,您的迭代器無效。做

k = x.erase(k); 
+1

有在這種情況下,雙增量的問題。以上解決了它。 – Egon 2010-10-05 18:42:06

+0

你是絕對正確的,感謝 – Benoit 2010-10-05 18:42:42

8

只是FWIW,你在說什麼也可以做(舉一個例子)std::list::remove_if

template <class T> 
class odd { 
    bool operator()(T const &value) { 
     return value % 2 != 0; 
    } 

}; 

// ... 
x.remove_if(odd); 

使用C++ 0x和/或Boost lambda,您可以單獨定義even來做到這一點,這對於這樣的微不足道的情況非常方便。從理論上講,你可以在適當的位置的std :: bind1st,的std :: bind2nd,性病的組合::平等和std ::模量也定義了這一點 - 但(IMO)的結果將是足夠很難破譯,這將是不宜。

注意std::list::remove_if(不像std::remove_if)實際上會刪除你問的項目已刪除,而std::remove_if通常需要與erase調用實際抹去刪除的項目相結合。

+0

夥計!不知道關於Boost Lambda ......這真是太棒了。真的要學習STL&Boost更好......會讓我的C++時代變得更加輕鬆。那時我非常反對使用外部庫......哈哈。這就是當他們教你如何在學校編寫集合班時所發生的事情,但忽略說「是的......但實際上並沒有寫這些永遠的事實」 – mpen 2010-10-06 00:52:00

+0

@Mark:我不確定我會說*永遠不會*編寫自己的集合類(有些東西,如環形緩衝區,默認不包括),但我*會*說* 1)只在必要時做,2)確保它們是「集合」作爲C++標準定義了這些術語,所以你可以將它們與標準算法,迭代器等一起使用。 – 2010-10-06 01:13:04

+0

呃..這就是我的意思。如果它們已經存在,不要寫下它們;)實際上很多情況下,你不幸需要專門的收藏。 – mpen 2010-10-06 01:35:50

3

而是寫作的另一個爲(;;)循環迭代一個STL容器,整個事情通常可以用STL算法和lambda表達式做得更快。

你的示例代碼可以改寫爲:

list<int> x; 

int i = 0; 
generate_n(back_inserter(x), 10, [&i](){ return i++; }); 

copy(x.begin(), x.end(), ostream_iterator<int>(cout, " ")); 
cout << endl; 

x.remove_if([](int n){ return n%2==0; });