【问题标题】:Erase element iterating in a while loop擦除在while循环中迭代的元素
【发布时间】:2020-06-08 07:06:00
【问题描述】:

我尝试在 deque 迭代 while 循环中删除元素。但是似乎在删除一个元素后,循环会跳过下一个元素。 代码如下

 Example program
#include <iostream>
#include <string>
#include <deque>
#include <algorithm>
using namespace std;

deque<int*> queue;
int main()
{
  int * a1 = new int(0);
  int * a2 = new int(2);
  int * a3 = new int(3);
  int * a4 = new int(4);
  int * a5 = new int(5);
  queue.push_back(a1);
  queue.push_back(a2);
  queue.push_back(a3);
  queue.push_back(a4);
  queue.push_back(a5);

    deque<int * >::iterator it = queue.begin();

    while(it != queue.end())
    {
       std::cout << "Element :" << **it << std::endl;
       //remove all elements are divided by 2
       if((**it&1) == 0)
       {
        deque<int * >::iterator cur = (it+1);
        std::cout << "Erase " << **it << std::endl;
        queue.erase(std::remove(queue.begin(), queue.end(), *it), queue.end());
        delete *it;
        it = cur;
       }
       else
       {
           ++it;
       }
    }
    std::cout << "End" << std::endl;     
}

输出如下

*元素:0 擦除 0

元素:3

元素:4 擦除 4

结束*

似乎跳过了元素 2 和 5。

【问题讨论】:

  • std::deque&lt;&gt;::erase: "所有迭代器和引用无效除非被擦除的元素是在容器的末尾或开头,在这种情况下,只有迭代器和对已擦除元素的引用无效”.
  • 迭代时不要修改数据结构!
  • 这意味着只做 queue.erase(it) 。这样可以吗?

标签: c++ deque


【解决方案1】:

您有未定义的行为,因为您在 delete *it; 处取消引用无效的迭代器。要解决您眼前的问题,您需要类似

int * to_del = *it;
it = queue.erase(it);
delete to_del;

但是,您也应该避免在int 足够的情况下使用int *,并在&lt;algorithm&gt; 中有适用的内容时编写循环

bool is_even(int i) { return (i % 2) == 0; }

std::deque<int> queue { 0, 2, 3, 4, 5 };
queue.erase(std::remove_if(queue.begin(), queue.end(), is_even), queue.end());

【讨论】:

  • 或者,从 C++20 开始,按照[deque.erasure]/2std::erase_if(queue, [](int x) { return (i % 2) == 0; });
猜你喜欢
  • 2019-08-23
  • 1970-01-01
  • 2016-11-22
  • 1970-01-01
  • 2014-06-11
  • 2011-03-22
  • 2020-07-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多