如何从cpp中的std::list中每隔一秒删除一个元素



我试图从std::list中每隔一秒删除一个元素,但当我运行erase((时,我会遇到段错误(核心转储(。

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

从第二项开始: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;
}

有关您的方法不起作用的原因的详细解释,请参阅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方法调用配对,是从范围中删除特定元素的算法。在这里,它变得有点棘手——我们想删除每一个元素,所以我们需要一个谓词,它将只为列表中的偶数位置返回true。我们使用用lambda init捕获初始化的成员计数器来实现它。

编辑:正如MSchanges在评论中正确指出的那样,使用std::list::remove_if<algorithm>erase-remove习语的高级解决方案。它利用了内部std::list实现的优势,加上键入:不那么尴尬

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

与原件相反:

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

删除列表中的元素会使相应的迭代器无效,因此它不能再用于解引用或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;
}