列表迭代器 Remove()

2022-01-07 00:00:00 list c++ stl

我有一个列表迭代器,它遍历列表并删除所有偶数.我可以使用列表迭代器很好地打印出数字,但我不能使用列表的 remove() 并传入取消引用的迭代器.

I have a list iterator that goes through a list and removes all the even numbers. I can use the list iterator to print out the numbers fine but I cannot use the list's remove() and pass in the dereferenced iterator.

我注意到当 remove() 语句生效时,*itr 被破坏了?有人能解释一下吗?

I noticed that when the remove() statement is in effect, *itr gets corrupted? Can somebody explain this?

#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
        }
    }
}

推荐答案

您的上述代码存在一些问题.首先,remove 将使指向已删除元素的任何迭代器无效.然后继续使用迭代器.很难判断哪些元素 remove 在一般情况下会擦除(尽管不是在你的情况下),因为它可以删除多个.

There are a few issues with your code above. Firstly, the remove will invalidate any iterators that are pointing at the removed elements. You then go on to continue using the iterator. It is difficult to tell which element(s) remove would erase in the general case (although not in yours) since it can remove more than one.

其次,您可能使用了错误的方法.Remove 将遍历列表中的所有项目以查找任何匹配的元素 - 在您的情况下这将是低效的,因为只有一个.看起来您应该使用 erase 方法,您可能只想擦除迭代器位置的项目.erase 的好处是它返回一个位于下一个有效位置的迭代器.使用它的惯用方式是这样的:

Secondly, you are probably using the wrong method. Remove will iterate through all of the items in the list looking for any matching elements - this will be inefficient in your case because there is only one. It looks like you should use the erase method, you probably only want to erase the item at the position of the iterator. The good thing about erase is it returns an iterator which is at the next valid position. The idiomatic way to use it is something like this:

//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 来做你正在做的事情:

Finally, you could also use remove_if to do the same as you are doing:

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

listA.remove_if(even);

相关文章