【问题标题】:List Iterator Remove()列表迭代器 Remove()
【发布时间】:2010-11-04 05:12:54
【问题描述】:

我有一个列表迭代器,它遍历一个列表并删除所有偶数。我可以使用列表迭代器很好地打印出数字,但我不能使用列表的 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
        }
    }
}

【问题讨论】:

    标签: c++ list stl


    【解决方案1】:

    上面的代码存在一些问题。首先,remove 将使任何指向已移除元素的迭代器无效。然后继续使用迭代器。在一般情况下(尽管不是您的情况),很难判断哪些元素 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() 之后引用未删除项目的列表迭代器应该保持有效。

      【讨论】:

        【解决方案3】:

        我们可以使用这样的东西吗:

        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() 之后增加迭代器,它会将您置于开头。

        【讨论】:

        • 这将适用于std::list 迭代器,因为这些迭代器仅在它们指向的元素被删除时才会失效。但这不适用于 std::vector 迭代器,因为当它们指向的元素或它们指向的元素之前的任何元素被删除时,这些迭代器将失效。
        【解决方案4】:

        由于迭代器依赖于保持不变的结构长度,因此大多数迭代器不允许在使用迭代器时更改列表。如果要遍历并更改列表,则必须使用独立于迭代器的循环。

        【讨论】:

        • 我必须指出,STL 迭代器对结构的长度没有任何依赖性。迭代器通常允许您删除某些元素,例如向量迭代器允许您删除迭代器之后的项目,列表迭代器允许您删除迭代器未指向的任何内容
        猜你喜欢
        • 2012-10-11
        • 1970-01-01
        • 1970-01-01
        • 2019-07-05
        • 1970-01-01
        • 1970-01-01
        • 2018-04-26
        • 2018-04-05
        • 2012-01-14
        相关资源
        最近更新 更多