代码之家  ›  专栏  ›  技术社区  ›  DarthRubik

在使用列表删除之后,迭代器如何不无效

  •  -1
  • DarthRubik  · 技术社区  · 6 年前

    如果我理解 this 表正确,a std::list 从中删除项后,仍然具有有效的迭代器。所以在我看来,这意味着这是有效的代码:

    #include <list>
    
    
    int main()
    {
        std::list<int> list;
        for (int x = 0; x < 20; x++)
        {
            list.push_back(x);
        }
        for (auto iter = list.begin(); iter != list.end(); ++iter)
        {
            if (*iter % 2)
            {
                list.erase(iter);
            }
        }
    }
    

    即使删除了every偶数项,我们仍然可以使用迭代器转到下一项。

    在我看来,我想我不明白一个人如何才能完成这项能力,而不付出一些可怕的性能代价(是的,我意识到,如果性能是我现在的样子,我就不应该使用 std::列表 )。

    那么这通常是如何实现的呢?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Remy Lebeau    6 年前

    在a中 std::list 这个 erase() 方法使已擦除的元素的所有引用和迭代器无效。对其他元素的引用/迭代器不受影响。

    但是,您正在尝试在迭代器无效后增加它。这行不通,行为未定义。 擦除() 将迭代器返回给列表中的下一个元素,因此您需要使用类似的方法:

    auto iter = list.begin();
    while (iter != list.end())
    {
        if (*iter % 2)
            iter = list.erase(iter); // or list.erase(iter++);
        else
            ++iter;
    }
    

    或:

    auto iter = list.begin();
    while (iter != list.end())
    {
        auto i = iter++;
        if (*i % 2)
            list.erase(i);
    }
    

    另一种解决方案是使用 std:::list::remove_if() 方法,让它为您处理循环:

    list.remove_if( [](int i){ return (i % 2); } );