C++ 列表迭代器 Remove()

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1016307/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:24:56  来源:igfitidea点击:

List Iterator Remove()

c++liststl

提问by Steve

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() 并传入取消引用的迭代器。

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

我注意到当 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
        }
    }
}

回答by 1800 INFORMATION

There are a few issues with your code above. Firstly, the removewill 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) removewould erase in the general case (although not in yours) since it can remove more than one.

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

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 erasemethod, you probably only want to erase the item at the position of the iterator. The good thing about eraseis it returns an iterator which is at the next valid position. The idiomatic way to use it is something like this:

其次,您可能使用了错误的方法。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;
}

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

最后,您还可以使用remove_if与您正在做的相同的事情:

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

listA.remove_if(even);

回答by Jonathan Maddison

You can't use an iterator after you delete the element it referred to.

删除它引用的元素后,您不能使用迭代器。

However, list iterators which refer to non-deleted items after a remove()should remain valid.

但是,在 a 之后引用未删除项目的列表迭代器remove()应该保持有效。

回答by rimad

Could we use something like this:

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

container.erase(it++);

I tried on this example:

我试过这个例子:

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

and it displayed 3, as I wanted. Now I don't know if this is valid or one of those which "sometimes work and sometimes not".

它显示了我想要的 3。现在我不知道这是有效的还是“有时有效有时无效”的方法之一。

EDIT: Maybe it is because of compiler. For example, compiler I am using (GNU gcc-g++) is treating lists (std::) as circular, ie if I increase iterator after list->end() it puts you at the beginning.

编辑:也许是因为编译器。例如,我使用的编译器 (GNU gcc-g++) 将列表 (std::) 视为循环,即如果我在 list->end() 之后增加迭代器,它会将您置于开头。

回答by mnuzzo

Since iterators depend on the length of the structure remaining the same, most iterators do not allow a list to be changed while the iterator is in use. If you want to go through and change the list, you're going to have to use a loop independent of the iterator.

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