2009-06-19 128 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