【问题标题】:Safe way to continuously erase from a std::vector?从 std::vector 连续擦除的安全方法?
【发布时间】:2011-05-09 17:17:57
【问题描述】:

我认为下面的代码可以工作,但是当目标小部件位于矢量末尾时它会崩溃。

for(std::vector<AguiWidget*>::iterator it = children.begin();
        it != children.end(); ++it)
    {
        if((*it) == widget)
            it = children.erase(it);
    }

我希望它通过并删除它找到的任何小部件实例。我知道这种方法是 N^2 但由于这是事件驱动的,所以很好。我只是不知道为什么这会失败。当它出现时,'it' == 小部件。

谢谢

【问题讨论】:

标签: c++ vector iterator


【解决方案1】:

为了补充Blastfurnace 的答案,如果您向后执行,您也可以使用简单的for 循环来完成。

for (widgets::reverse_iterator it = children.rbegin(), end = children.rend();
     it != end; ++it)
{
  if (*it == widget) { children.erase(it.base()); }
}

【讨论】:

    【解决方案2】:

    您确实意识到您在比较指针,而不是取消引用,对吧?

    你能告诉我们如果你使用 remove-erase 成语会发生什么吗?这将更快(比您的代码更好)且正确:

    children.erase(std::remove_if(children.begin(), children.end(),
                                  std::bind1st(std::equal_to<AguiWidget*>(),
                                               widget)));
    

    另外,别忘了先删除指针。

    for_each_if(children.begin(), children.end(),
                std::bind1st(std::equal_to<AguiWidget*>(), widget),
                Delete());
    

    当然,您必须确保没有两个指针指向同一个对象。

    【讨论】:

      【解决方案3】:

      如果您想像这样使用擦除,您可能应该坚持使用列表。但问题是您使迭代器无效,然后尝试增加它。试试这个吧。

      for(std::vector<AguiWidget*>::iterator it = children.begin();
          it != children.end();)
      {
          if(*it == widget)
              children.erase(it++);
          else
              ++it;
      }
      

      请注意,我没有在 for 循环语句中递增迭代器。

      【讨论】:

      • 这是原始 for() 循环失败的关键原因。它总是在重新测试循环终止条件之前递增迭代器。在循环体中将迭代器更改为 end(),然后尝试 ++it 将您送入愚蠢之地。
      • 这里没有理由使用列表。
      • @Matthieu:我提到这一点是因为对于涉及删除内部元素的任务,列表比向量更有效。虽然使用向量执行此任务是完全合法的代码,但每次删除都会有很大的损失,因为所有后续项目都需要在内存中移动,这可能涉及大量的复制和内存重新分配。列表不会遇到这个问题,因为它们只需重新排列几个指针即可完成相同的事情。
      【解决方案4】:

      您可以使用erase-remove 习惯用法来擦除所有等于widget的元素。

      children.erase(remove(children.begin(), children.end(), widget), children.end());
      

      【讨论】:

        猜你喜欢
        • 2011-07-17
        • 1970-01-01
        • 2018-01-27
        • 1970-01-01
        • 1970-01-01
        • 2018-12-05
        • 2011-10-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多