【问题标题】:Erasing an element from a list container从列表容器中删除元素
【发布时间】:2012-12-28 10:57:06
【问题描述】:

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

好的,我正在从列表中删除元素。

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

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

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

当我写这段代码时擦除功能起作用:

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

我只需要了解为什么当我编写 i = lNo.erase(i) 而不是仅使用 lNo.erase(i) 时程序可以工作?

一个简单简洁的答案将不胜感激。 我知道不同的容器有不同的约束,那么我在原始代码中违反了哪个约束?。

【问题讨论】:

    标签: c++ list containers erase


    【解决方案1】:

    即使您的第二个代码也不正确。

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

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

    请注意,erase() 会删除该项并将迭代器返回到下一项。这意味着,擦除时不需要在代码中增加i;相反,您只需使用来自erase 的返回值更新i

    您可以将erase-remove idiom 用作:

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

    Live demo

    【讨论】:

      【解决方案2】:

      问题是您使用的迭代器不希望修改列表的链接。 因此,当您在列表中调用 erase() 时,链接会被有效地修改,因此您的迭代器不再有效。 i++ 语句不再起作用。

      但是,在第二个版本中,您将迭代器重新分配给仍然具有完整链接的有效对象,因此 i++ 语句仍然可以工作。

      在某些框架中,您有 2 种迭代器,一种能立即反映底层数据集正在发生的事情(这是您正在使用的),另一种不会改变它们的链接,无论发生在底层数据集(因此您不必使用第二版的奇怪技巧)。

      【讨论】:

      • 谢谢你们所有有用的答案。
      【解决方案3】:

      the documentation 中所述,erase 函数使传入的迭代器无效。这意味着它不能再次使用。循环无法继续使用该迭代器。

      文档还声明它返回一个迭代器到被擦除之后的元素。该迭代器有效,可用于继续。

      但是请注意,由于它返回一个迭代器到元素在被擦除的元素之后,因此不需要增加它来推进,否则将不会检查该元素的奇数。循环应该对此进行处理,并且仅在未完成擦除时才增加。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-03-05
        • 2014-12-19
        • 2013-11-25
        • 2016-05-29
        相关资源
        最近更新 更多