2009-06-19 134 views
14

我有一個列表迭代器遍歷列表並刪除所有的偶數。我可以使用列表迭代器打印出數字,但我無法使用列表的remove()並在解除引用的迭代器中傳遞。列表迭代器刪除()

我注意到,當remove()語句生效時,* itr被破壞?有人可以解釋這一點嗎?

#include <iostream> 
#include <list> 

#define MAX 100 

using namespace std; 

int main() 
{ 
    list<int> listA; 
    list<int>::iterator itr; 

    //create list of 0 to 100 
    for(int i=0; i<=MAX; i++) 
     listA.push_back(i); 

    //remove even numbers 
    for(itr = listA.begin(); itr != listA.end(); ++itr) 
    { 
     if (*itr % 2 == 0) 
     { 
      cout << *itr << endl; 
      listA.remove(*itr); //comment this line out and it will print properly 
     } 
    } 
} 

回答

41

上面的代碼有幾個問題。首先,remove將使指向已刪除元素的任何迭代器失效。然後你繼續使用迭代器。在一般情況下(雖然不在您的範圍內)很難判斷哪個元素remove會被刪除,因爲它可以刪除多個元素。

其次,您可能使用了錯誤的方法。刪除將遍歷列表中的所有項目,尋找任何匹配的元素 - 這在您的案例中效率低下,因爲只有一個。它看起來像你應該使用erase方法,你可能只想擦除迭代器位置的項目。關於erase的好處是它返回一個迭代器,它位於下一個有效位置。使用它的慣用方式是這樣的:

//remove even numbers 
for(itr = listA.begin(); itr != listA.end();) 
{ 
    if (*itr % 2 == 0) 
    { 
     cout << *itr << endl; 
     itr=listA.erase(itr); 
    } 
    else 
     ++itr; 
} 

最後,您還可以使用remove_if做同樣的,你正在做的:

bool even(int i) { return i % 2 == 0; } 

listA.remove_if(even); 
2

刪除引用的元素後,不能使用迭代器。

但是,引用remove()後的未刪除項目的列表迭代器應保持有效。

-1

由於迭代器依賴於結構的長度保持不變,大多數迭代器不允許在迭代器使用時更改列表。如果你想通過並改變列表,你將不得不使用獨立於迭代器的循環。

+4

我必須指出STL迭代器對結構長度沒有任何依賴性。迭代器通常允許你刪除某些元素,例如向量迭代器允許你刪除通過迭代器的項目,並且列表迭代器允許你刪除迭代器沒有指向的任何東西 – 2009-06-19 04:23:51

0

我們可以使用像這樣:

container.erase(it++); 

我想在這個例子:

int main(){ 

list<int>*a=new list<int>; 
a->push_back(1); 
a->push_back(2); 
a->push_back(3); 

list<int>::iterator I; 

I=a->begin(); ++I; 

a->erase(I++); 
cout<<*I<<endl; 
} 

它顯示3,因爲我想要的。現在我不知道這是否有效,或者是「有時工作,有時不工作」。

編輯:也許這是因爲編譯器。例如,我正在使用的編譯器(GNU gcc-g ++)將列表(std :)作爲循環處理,即如果我在list-> end()之後增加迭代器,它會將您置於開頭。

+0

這對'std :: list'迭代器是有效的,因爲這些迭代器只有在它們指向的元素被刪除時纔會失效。但是這對於'std :: vector'迭代器不起作用,因爲當它們指向的元素或它們指向的元素之前的任何元素被刪除時,這些迭代器將失效。 – David 2017-09-24 07:54:32