【问题标题】:Erasing data in vector via loop causing breakpoints [duplicate]通过循环擦除向量中的数据导致断点[重复]
【发布时间】:2017-06-13 07:12:15
【问题描述】:

我有一个类对象向量(子弹),它在大多数情况下都有效。但是,一旦我尝试删除项目符号,它就会循环回来,然后导致断点。 “基本游戏.exe 已触发断点。”我试过前后迭代,但总是卡住。

我正在使用 SFML,对象是具有位置、旋转和大小的矩形。

    for (it = bullets.end(); it != bullets.begin(); it--)
    {
        it->draw(game); 
        it->move();
        if (it->bullet.getPosition().x > 800)
        {
            bullets.erase(it);
        }
    }

我是编码新手,所以如果您需要其他信息,请尝试提供。

【问题讨论】:

  • std::vector 中删除元素将使其所有迭代器(在本例中为it)无效,调用未定义的行为(因为您试图在下一个循环周期中使用it-1,@ 987654326@).
  • 有效的是 bullets.erase(it--);但是你必须重新考虑你的 for 循环
  • 即使第一个it->draw(game); 也是UB(因为itend())。
  • 你可能想看看erase/remove idiom

标签: c++ visual-studio sfml


【解决方案1】:

当您在向量上调用 erase() 时,迭代器变得无效。 相反,请考虑尝试以下操作:

 for (auto it = bullets.begin(); it != bullets.end();)
 {
    it->draw(game); 
    it->move();
    if (it->bullet.getPosition().x > 800)
    {
      it = bullets.erase(it);
    }
    else
    {
      it++;
    }
  }

【讨论】:

  • 我把我的代码改成了这个,它工作了。谢谢,但你能解释一下为什么这行得通而我的不行吗?
  • @Mitchell 在您调用擦除之后,迭代器变得无效。 erase() 将迭代器返回到被擦除元素之后的元素,因此再次验证迭代器,这就是上面代码中发生的情况
  • @Kevin 当然,我误读并错过了erase() 的返回用于重置it。 Downvode => upvote。
【解决方案2】:

你可以修复你的循环

for (auto& bullet : bullets) {
    bullet.draw(game);
    bullet.move();
}
bullets.erase(std::remove_if(bullets.begin(), bullets.end(),
                             [](const auto& bullet) {
                                 return bullet.getPosition().x > 800;
                             }),
              bullets.end());

【讨论】:

  • 我认为你的擦除有点错误(除了bullet::erase 而不是bullets.erase)。你也需要给出结束迭代器。
  • @Kevin:确实,错别字已修复。
猜你喜欢
  • 1970-01-01
  • 2021-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 2018-10-19
  • 2020-12-21
  • 2015-08-12
相关资源
最近更新 更多