我一直在努力把一个向量对象放到一个我正在做的项目中,我读了一些我能找到的东西,然后决定试一试。
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;
}
}发布于 2015-04-17 15:41:34
如果可能的话,应该使用详细说明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;
}发布于 2015-04-17 15:47:05
通过使用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函数。如果它是一个异常,您可以在擦除过程中引入一个bug。在这种情况下,您可能希望使用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()调用将从一开始就删除这些项。除此之外,这些项目仍然是完全有效的条目,因此在您最终删除它们之前,您可以以您希望的任何方式处理它们。
https://stackoverflow.com/questions/29703553
复制相似问题