【问题标题】:Unable to remove all object from vector无法从矢量中删除所有对象
【发布时间】:2021-12-03 02:31:23
【问题描述】:

所以基本上我有一个名为“事物”的对象向量,我在控制台上填充它。这些是我用来填充它们的对象的名称(汤姆、硬币、硬币、炸弹)。

for (int i = 0; i < 5; i++){
  for (Thing * t : *locations[i]->getThings()) {
     if (t->getName().compare("bomb") == 0){
        for (Thing * all : *locations[i]->getThings()){
            if(all->getName().compare("tom") != 0){
                 locations[i]->remove(all);
             }
         } 
      }
   }
}

这段代码每次都会运行以检查列表中是否有一个名为炸弹的“事物”对象,并将删除除 tom 之外的所有其他对象。

因此,从上面的填充示例中,预期的列表应该只是 {tom}。但是,当代码运行时,它是 {tom, coin},这意味着它无法删除其他“非 tom”对象

【问题讨论】:

  • 在迭代容器时从容器中移除一个项目是充满危险的。考虑改用the Erase-Remove idiom
  • 当您从容器中删除它指向的对象时,您的迭代器(请考虑将其称为 it 而不是 all)可能会变得无效。
  • @TimRandall all 不是迭代器
  • 请不要通过破坏您的帖子为他人增加工作量。通过在 Stack Exchange 网络上发帖,您已在 CC BY-SA 4.0 license 下授予 Stack Exchange 分发该内容的不可撤销的权利(即无论您未来的选择如何)。根据 Stack Exchange 政策,帖子的非破坏版本是分发的版本。因此,任何破坏行为都将被撤销。如果您想了解更多关于删除帖子的信息,请参阅:How does deleting work?

标签: c++ object vector


【解决方案1】:

问题是您正在修改 Things 向量,而您仍在迭代它,因此您将无效 for 循环正在使用的迭代器,这是 未定义的行为 em>。

您可以改为使用Erase-Remove idiom

const auto is_bomb = [](const Thing *t){ return t->getName() == "bomb"; };
const auto is_not_tom = [](const Thing *t){ return t->getName() != "tom"; };
...
auto *things = locations[i]->getThings();
if (std::any_of(things->begin(), things->end(), is_bomb)){
    things.erase(
        std::remove_if(things->begin(), things->end(), is_not_tom),
        things->end()
    );
}

或者,如果您使用的是 C++20 或更高版本:

const auto is_bomb = [](const Thing *t){ return t->getName() == "bomb"; };
const auto is_not_tom = [](const Thing *t){ return t->getName() != "tom"; };
...
auto *things = locations[i]->getThings();
if (std::any_of(things->begin(), things->end(), is_bomb)){
    std::erase_if(*things, is_not_tom);
}

【讨论】:

    猜你喜欢
    • 2012-06-19
    • 2020-10-26
    • 2017-02-21
    • 2013-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-01
    相关资源
    最近更新 更多