我正在尝试从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;
}
答案 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_if
与erase
方法调用配对,是 算法,用于从范围中删除特定元素。在这里,它有点棘手-我们要删除每个 second 元素,因此我们需要一个谓词,该谓词仅对列表中的偶数位置返回true
。我们通过使用lambda init capture初始化的成员计数器来实现它。
编辑:正如 alters 在评论中正确指出的那样,使用std::list::remove_if
是erase-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;
}