如何从cpp的std :: list中删除第二个元素?

时间:2018-11-13 16:28:50

标签: c++

我正在尝试从std :: list中删除第二个元素,但是当我运行delete()时出现段错误(核心转储)。

#include <bits/stdc++.h>

using namespace std;

int main()
{
    list <int> num_list;
    list <int> :: iterator it;
    num_list.push_back(1);
    num_list.push_back(2);
    num_list.push_back(3);
    num_list.push_back(4);
    num_list.push_back(5);
    cout << num_list.size() << endl;
    it = num_list.begin();
    advance(it, 1);
    for(it; it != num_list.end(); advance(it, 2)) {
        num_list.erase(it);
    }
    for(it = num_list.begin(); it != num_list.end(); ++it) {
        cout << *it << " ";
    } 
    cout << endl;
    return 0;
}

3 个答案:

答案 0 :(得分:9)

从第二项开始:next(num_list.begin(), 1)erase方法将迭代器返回到已删除项目的下一个项目。因此,您只需使用++运算符即可执行步骤2。

int main()
{
    list<int> num_list;
    num_list.push_back(1);
    num_list.push_back(2);
    num_list.push_back(3);
    num_list.push_back(4);
    num_list.push_back(5);
    cout << num_list.size() << endl;

    for (auto it = next(num_list.begin(), 1); it != num_list.end();) {
        it = num_list.erase(it);
        if (it != num_list.end())
            ++it;
    }
    for (auto it = num_list.begin(); it != num_list.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;
    return 0;
}

答案 1 :(得分:7)

有关为什么您的方法不起作用的详细说明,请参见 Stepan Lechner 的答案。

使用std::remove_if和lambda表达式的完全不同的方法:

int main() {
    std::list<int> ints{1, 2, 3, 4, 5};

    auto position = std::remove_if(ints.begin(), ints.end(),
            [counter = 0](const auto x) mutable {
        return ++counter % 2 == 0;
    });

    ints.erase(position, ints.end());

    for(const auto x : ints) {
        std::cout << x << ' ';
    }
}

std::remove_iferase方法调用配对,是 算法,用于从范围中删除特定元素。在这里,它有点棘手-我们要删除每个 second 元素,因此我们需要一个谓词,该谓词仅对列表中的偶数位置返回true。我们通过使用lambda init capture初始化的成员计数器来实现它。

编辑:正如 alters 在评论中正确指出的那样,使用std::list::remove_iferase-remove的{​​{1}}惯用语的高级解决方案。它利用内部<algorithm>实现的优点,而且键入不太麻烦

std::list

与原始版本相反:

// *ints* being the list itself
ints.remove_if([counter = 0](const auto x) mutable {
    return ++counter % 2 == 0;
});

答案 2 :(得分:4)

删除列表中的元素会使相应的迭代器无效,因此不得再将其用于取消引用或advancing。指向除已删除元素之外的其他元素的迭代器不会受到影响。

因此,您只需要记住要删除的迭代器位置,并在擦除“ toDelete”位置之前使原始迭代器前进:

int main()
{
    list <int> num_list;
    num_list.push_back(1);
    num_list.push_back(2);
    num_list.push_back(3);
    num_list.push_back(4);
    num_list.push_back(5);

    size_t size = num_list.size();
    cout << size << endl;

    list <int> :: iterator it = num_list.begin();
    while(size--) {
        auto toDelete = it;
        it++;

        if (size%2==1)
            num_list.erase(toDelete);
    }

    for(it = num_list.begin(); it != num_list.end(); ++it) {
        cout << *it << " ";
    }
    cout << endl;
    return 0;
}