In the code of my game, I want to remove some elements from 开发者_如何学运维a list
,
list::erase
I have to break after that function because I think
the list
becomes "outdated". This causes a little flicker and I want to
try to remove it.
The current code is this:
for(list<Arrow*>::iterator it = arrows.begin(); it != arrows.end(); it++)
{
Arrow* a = (*it);
if(a->isActive() == true)
{
a->update();
}
else
{
arrows.erase(it);
break;
}
}
Thank you in advance!
Edit: Sorry, I was confused with vector and list. Got the answer, thanks!
you should do:
it = arrows.erase(it);
//
list<Arrow*>::iterator it = arrows.begin();
while (it != arrows.end())
{
Arrow* a = (*it);
if(a->isActive())
{
a->update(); ++it;
}
else{ // delete (a); ???
it=arrows.erase(it);}
}
I am confused, you say vector and in your example you are using a list.
List is implemented with a double linked-list (actually it is likely to be implemented, because the standard fix just the complexity and not the details). The iterator after erasing are still valid. http://www.cplusplus.com/reference/stl/list/erase/
Erasing in the middle with vector is slow and also invalided all the iterators and references.
Like everyone said you example is confusing. If you want delete in the mid of your container and if you are using
1>vector: Then every iterator and reference after the point of erase is invalidated. Also vector deleting from mid of vector will causing element behind it to shift which might considered slow if you want performance.
2>list: Then only the deleted iterator and reference is invalidated.
Either way using the erase-remove idiom is preferred when you want to delete some element in the middle of stl sequence container.
The proper way to filter out items in a standard library container is to use the Erase-Remove Idiom. Because you're using a member function as the test in the loop, you should adapt the example to use std::remove_if()
.
You can implement this in a short and sweet (provided you like functional programming) way:
#include <algorithm>
#include <functional>
arrows.erase(std::remove_if(
arrows.begin(), arrows.end(), std::mem_fun(&Arrow::isActive)
));
This will work for std::vector<>
, std::deque<>
, std::list<>
etc. regardless of implementation and iterator invalidation semantics.
Edit: I see you're also using the Arrow::update()
method inside the loop. You can either do a double pass on the list, use a function object to call both methods or write the loop manually.
In the last case, you can use the it = arrows.erase(it);
trick, but this will only be efficient for std::list<>
. The loop will have O(n^2)
complexity for the
std::vector<>
and std::deque<>
containers.
精彩评论