[英]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_if
与vector::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::remove
和std::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.