c ++矢量对象.erase

时间:2015-04-17 15:33:38

标签: c++ class vector

我一直在努力将矢量对象放入我正在做的项目中 我已经阅读了关于这样做的一点点,并决定试一试。

      std::vector<BrickFalling> fell;
      BrickFalling *f1;

我创建了矢量。下一部分工作正常,直到我得到擦除 部分。

if(brickFall == true){

f1 = new BrickFalling;

f1->getBrickXY(brickfallx,brickfally);

fell.push_back(*f1);
brickFall = false;
}
// Now setup an iterator loop through the vector

vector<BrickFalling>::iterator it;

for( it = fell.begin(); it != fell.end(); ++it ) {

   // For each BrickFalling, print out their info

   it->printBrickFallingInfo(brick,window,deadBrick);

   //This is the part im doing wrong /////
   if(deadBrick == true)// if dead brick erase
   {
       BrickFalling[it].erase;//not sure what im supposed to be doing here
       deadBrick = false;
   }
}

2 个答案:

答案 0 :(得分:4)

您可以使用std::remove_ifvector::erase完全避免此问题。

auto it = 
   std::remove_if(fell.begin(), fell.end(), [&](BrickFalling& b) 
              { bool deadBrick = false;      
                b.printBrickFallingInfo(brick,window,deadBrick);
                return deadBrick; });

   fell.erase(it, fell.end());

这避免了循环的手写。

通常,您应该努力以这种方式为序列容器编写擦除循环。原因是在自己编写循环时很容易进入“无效迭代器”场景,即每次擦除时都不记得重置循环迭代器。

我不知道的代码唯一问题是printBrickFallingInfo函数。如果throws出现异常,则可能会在擦除过程中引入错误。在这种情况下,您可能希望使用try/catch块保护呼叫,以确保不会过早离开功能块。

编辑:

正如评论所述,您的print...功能可能只是为了确定砖块是否在下降而做了太多工作。如果你真的想要打印东西并做更多可能导致某种副作用的事情,那么另一种类似的方法就是使用std::stable_partition

使用std::stable_partition,您可以“暂停”删除,只需将要删除的元素移动到容器中的一个位置(在开头或结尾) all,而不会使这些项无效。这是主要区别 - 使用std::stable_partition,您要做的就是移动要处理的项目,但移动后的项目仍然有效。 std::removestd::remove_if不是这样 - 移动的项目只是无效,任何使用这些项目的尝试都是未定义的行为。

auto it = 
   std::stable_partition(fell.begin(), fell.end(), [&](BrickFalling& b) 
              { bool deadBrick = false;      
                b.printBrickFallingInfo(brick,window,deadBrick);
                return deadBrick; });

   // if you need to do something with the moved items besides
   // erasing them, you can do so.  The moved items start from
   // fell.begin() up to the iterator it.
   //...
   //...
   // Now we erase the items since we're done with them
   fell.erase(fell.begin(), it);

这里的区别在于我们最终擦除的项目将位于分区迭代器it的左侧,因此我们的erase()调用将从中删除项目一开始。除此之外,这些项目仍然是完全有效的条目,因此您可以在最终删除它们之前以任何方式使用它们。

答案 1 :(得分:3)

应尽可能使用详细说明remove_if使用的其他答案。但是,如果您的情况不允许您使用remove_if编写代码,这可能发生在更复杂的情况下,您可以使用以下内容:

您可以将vector::erase与迭代器一起使用以删除该位置的元素。然后使用的迭代器失效。 erase返回一个指向下一个元素的新迭代器,因此您可以使用该迭代器继续。

你最终得到的是一个循环:

for( it = fell.begin(); it != fell.end(); /* iterator updated in loop */ )
{
     if (shouldDelete)
         it = fell.erase(it);
     else
         ++it;
}