繁体   English   中英

C ++矢量对象.erase

[英]c++ vector object .erase

我一直在努力将矢量对象放到项目中,正在做的事,我已经读到了一些关于这样做的信息,并决定尝试一下。

      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;
   }
}

通过将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您可以“暂停”擦除操作,只需将要擦除的元素移动到容器中某个位置(在开始或结束时), 而无需使这些项目无效 那是主要区别-使用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()调用将从一开始就删除这些项目。 除此之外,这些项目仍然是完全有效的条目,因此您可以在最终删除它们之前以任何希望的方式使用它们。

尽可能详细地使用详细说明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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM