从列表容器中删除元素

Jos*_*osh 3 c++ containers list erase

我很难理解代码为什么会这样表现.首先,我已经阅读了相关的回答材料,但仍然发现了解释.所以我想知道是否有人可以用简单的方式解释这一点.

好的,所以我从列表中删除元素.

该列表包含奇数和偶数的int元素.这一部分我明白了.这是我最初编写的代码,用于从列表中删除奇数

for(list<int>::iterator i = lNo.begin(); i != lNo.end(); i++)
    {
        if(*i%2 == 0 )
        {
             lNo.erase(i);
        }
        else
        {
             cout << " " << *i;
        }
     }
Run Code Online (Sandbox Code Playgroud)

使用此代码,程序根本无法编译,我读了一条消息,说明程序必须关闭.

擦写功能在我编写此代码时起作用:

for(list<int>::iterator i = lNo.begin(); i != lNo.end(); i++)
    {
        if(*i%2 == 0 )
        {
             i = lNo.erase(i);  
        }
        else
        {
            cout << " " << *i;
        }
   }
Run Code Online (Sandbox Code Playgroud)

我只需要理解为什么程序在我编码i = lNo.erase(i)而不是只用lNo.erase(i)时有效?

一个简单的简洁答案将非常感激.我知道不同的容器有不同的约束,所以我违反了原始代码的约束?

R. *_*des 6

文档所述,该erase函数使传入的迭代器无效.这意味着它不能再次使用.循环不能继续使用该迭代器.

该文档还指出它将一个迭代器返回到擦除后的元素.该迭代器有效并可用于继续.

但请注意,由于它在删除之后将元素返回到元素,因此无需将其递增以进行前进,或者不会检查该元素的奇数.循环应该捕获它,并且只在没有擦除时增加.


Naw*_*waz 5

即使你的第二个代码是错误的.

正确的代码应该是这样的:

for(list<int>::iterator i = lNo.begin(); i != lNo.end(); /*NOTHING HERE*/ )
{
    if(*i%2 == 0 )
    {
         i = lNo.erase(i);  
    }
    else
    {
        cout << " " << *i;
        ++i; //INCREMENT HERE, not in the for loop
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,erase()擦除项目并将迭代器返回到下一个项目.这意味着,i擦除时不需要增加代码; 相反,您只需要i使用返回的值进行更新erase.

你可以erase-remove idiom用作:

lNo.erase(std::remove_if(lNo.begin(),
                         lNo.end(),
                         [](int i) { return i%2 == 0; }), 
                         lNo.end());
Run Code Online (Sandbox Code Playgroud)

现场演示