首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c++矢量对象.erase

c++矢量对象.erase
EN

Stack Overflow用户
提问于 2015-04-17 15:33:37
回答 2查看 199关注 0票数 0

我一直在努力把一个向量对象放到一个我正在做的项目中,我读了一些我能找到的东西,然后决定试一试。

代码语言:javascript
复制
      std::vector<BrickFalling> fell;
      BrickFalling *f1;

我创造了向量。下一篇文章很好,直到我到达擦除部分。

代码语言:javascript
复制
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;
   }
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-04-17 15:41:34

如果可能的话,应该使用详细说明remove_if使用的另一个答案。但是,如果您的情况不允许您使用remove_if编写代码(这在更复杂的情况下可能发生),则可以使用以下方法:

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

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

代码语言:javascript
复制
for( it = fell.begin(); it != fell.end(); /* iterator updated in loop */ )
{
     if (shouldDelete)
         it = fell.erase(it);
     else
         ++it;
}
票数 3
EN

Stack Overflow用户

发布于 2015-04-17 15:47:05

通过使用std::remove_ifvector::erase,您可以完全避免这个问题。

代码语言:javascript
复制
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函数。如果它是一个异常,您可以在擦除过程中引入一个bug。在这种情况下,您可能希望使用try/catch块来保护调用,以确保您不会过早离开函数块。

编辑:

正如注释所指出的那样,您的print...函数可能做了太多的工作来确定砖是否正在脱落。如果你真的想打印一些东西,做更多可能会产生某种副作用的事情,另一种本质上类似的方法就是使用std::stable_partition

使用std::stable_partition,您可以“暂停”擦除,只需将要删除的元素移动到容器中的一个位置(在开始或结束时),所有这些元素都不会使这些项失效。这是主要的区别--对于std::stable_partition,您所要做的就是移动要处理的项,但是移动后的项仍然有效。对于std::removestd::remove_if,情况并非如此--移动的项只是无效的,任何试图将这些项当作仍然有效的尝试都是未定义的行为。

代码语言:javascript
复制
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()调用将从一开始就删除这些项。除此之外,这些项目仍然是完全有效的条目,因此在您最终删除它们之前,您可以以您希望的任何方式处理它们。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29703553

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档