【发布时间】:2013-03-07 13:55:25
【问题描述】:
我在调用以下代码时遇到了问题:
#include<deque>
using namespace std;
deque<int> deq = {0,1,2,3,4,5,6,7,8};
for(auto it = deq.begin(); it != deq.end(); it++){
if(*it%2 == 0)
deq.erase(it);
}
导致分段错误。在查看问题后,我发现问题在于 STL 管理双端队列迭代器的方式:如果被擦除的元素更接近双端队列的末尾,则用于指向已擦除元素的迭代器现在将指向 NEXT元素,但不是 vector::iterator 所做的前一个元素。我知道将循环条件从 it != deq.end() 修改为 it < deq.end() 可能会解决问题,但我只是想知道是否有办法以“标准形式”遍历和擦除双端队列中的某些元素,以便代码可以也兼容其他容器类型。
【问题讨论】:
-
使用
std::remove_if。 -
您可以在分配给 std::remove_if 的函数(或函数对象)内执行操作,然后您仍然可以使用 std::remove_if(如@Fraser 建议的那样)。我会建议使用通用算法而不是普通循环,因为循环对您的意图不够清晰。另外,我认为同时修改和遍历容器是危险的。
-
@chris 你能提供一个deque的remove_if例子吗?我发现最后的 deque::erase(remove_if(...)) 不会删除正确的项目。 (实际上,remove_if 保持双端队列的顺序不变,但在其中放置了空格。)g++8/C++17.
-
@Daniel,您很有可能遇到了
erase的常见错误并忘记传递第二个参数,这意味着它会删除一个元素。它works here。不过,这七年后,你终于可以通过std::erase_ifdo a bit better with C++20。如果remove_if留下“空白”,这听起来像是某种错误,无论是在实现中还是在使用中。