【问题标题】:Erase multiple elements in deque C++擦除双端队列 C++ 中的多个元素
【发布时间】:2020-08-05 20:42:19
【问题描述】:

我试图在下面的“while”循环中删除双端队列中的多个元素,但我的程序没有给出正确的结果。

问题背景:

packet_deque 包含 9 个 Packet 对象 - 其中一些已发送,其他未发送。

#include <deque> 
#include <iostream> 

class Packet
{
public:
    void set_sent() { sent = true; };
    bool get_sent() { return sent; };
private:
    /* members of Test class */
    bool sent = false;
};

int main()
{ 
    size_t MAX = 9;
    std::deque<Packet> packet_deque(MAX);
    unsigned int i = 0;

    std::deque<Packet>::iterator itr = packet_deque.begin();
    printf("Before erasing sent packets - packet_dequeue size: %d \n", packet_deque.size());
    // initialise the packet queue - creating some sent packets
    for (; itr != packet_deque.end(); ++itr) 
    {
        // set some sent packets
        if (i % 3 == 0) 
        {
            itr->set_sent();
        }
        printf("packet_deque[%d]: %s\n", i, itr->get_sent() ? "sent" : "not_sent");
        ++i;
    }
    printf("\n");

    // erase sent packets in packet_dequeue
    itr = packet_deque.begin();
    while (itr != packet_deque.end())
    {
        if (itr->get_sent())
        {
            // erase the element and do NOT move the pointer
            packet_deque.erase(itr);
        }
        else
        {
            // move to next element
            ++itr;
        }
    }

    printf("After erasing sent packets - packet_dequeue size: %d \n", packet_deque.size());
    for (itr = packet_deque.begin(), i = 0; itr != packet_deque.end(); ++itr) 
    {
        printf("packet_deque[%d]: %s\n", i, itr->get_sent() ? "sent" : "not_sent");
        ++i;
    }
} 

终端输出为:

Before erasing sent packets - packet_dequeue size: 9 
packet_deque[0]: sent
packet_deque[1]: not_sent
packet_deque[2]: not_sent
packet_deque[3]: sent
packet_deque[4]: not_sent
packet_deque[5]: not_sent
packet_deque[6]: sent
packet_deque[7]: not_sent
packet_deque[8]: not_sent

After erasing sent packets - packet_dequeue size: 5 
packet_deque[0]: not_sent
packet_deque[1]: not_sent
packet_deque[2]: not_sent
packet_deque[3]: not_sent
packet_deque[4]: not_sent

问题:

由于while 循环只是删除了sent 数据包,我预计有 6 个未发送的数据包,但只有 5 个。 我无法弄清楚出了什么问题... 为什么最终结果只包含 5 个未发送数据包而不是 6 个未发送数据包?

【问题讨论】:

  • 使用erase / remove_if 成语。无需编写循环。
  • itr = packet_deque.erase(itr);
  • 删除元素后,迭代器不再有效。
  • 通常的方法是erase(remove(... / erase(remove_if(.....
  • packet_deque.erase(std::remove_if(packet_deque.begin(), packet_deque.end(), [](Packet&amp; p) { return p.get_sent(); }), packet_deque.end()); -- 没有循环。

标签: c++ iterator containers deque


【解决方案1】:

一般来说,从双端队列中删除后,所有迭代器都会失效。您的代码在 while 条件中使用了无效的迭代器。

但是erase 返回一个新的有效迭代器,该迭代器指向被擦除后的元素,所以正确的代码是

itr = packet_deque.erase(itr);

【讨论】:

    【解决方案2】:

    使用

    itr = packet_deque.erase(itr);
    

    否则当前迭代器无效。

    【讨论】:

      【解决方案3】:

      引用doc

      所有迭代器和引用都无效,除非被擦除的元素位于容器的末尾或开头,在这种情况下,只有迭代器和对被擦除元素的引用无效。

      所以你的循环

      
          while (itr != packet_deque.end())
          {
              if (itr->get_sent())
              {
                  // erase the element and do NOT move the pointer
                  packet_deque.erase(itr);
              }
              else
              {
                  // move to next element
                  ++itr;
              }
          }
      

      实际上是错误的。

      编辑:你应该使用itr = packet_deque.erase(itr); 来获得一个有效的迭代器。

      【讨论】:

      • 您的回答并没有真正为 OP 提供解决方案。您只是指出发布的代码是错误的。您应该通过显示正确解决方案来改进您的答案。
      猜你喜欢
      • 1970-01-01
      • 2015-05-07
      • 2020-01-28
      • 1970-01-01
      • 2012-03-19
      • 1970-01-01
      • 2020-07-31
      • 2019-11-09
      • 2010-12-28
      相关资源
      最近更新 更多