I'm guessing many can already see the problem, but I'll explain anyway: When I call the mParticles.erase(pItr) function, the iterator pItr "obviously" is set to NULL. When I then try to increase pItr when the loop continues, I get an assertion error: "Expression: ("this->_Mycont != NULL",0)".
So how should I go on about erasing the current element from the std::vector array, without messing up the loop, when using iterators?
Ps: I read that using iterators is the "preferred" way of going through the elements in a std::vector array.. which is why I've started looking into it in the first place. Is that true, and what advantages does it have? I don't mind using either way, I'm happy to learn whatever is "better". :P
Thanks in advance. :)

Share this post

Link to post

Share on other sites

Erasing elements from a vector invalidates all iterators into that vector.

In your case, the loop construct assumes that pItr will be valid, when it may not be after a call to mParticles.erase(pItr).

You really want something like:

typedef std::vector<ParticlePtr> ParticleArray;

ParticleArray::iterator pItr = mParticles.begin();

while (pItr != mParticles.end()){ (*pItr)->Update(Timefactor);

if (!(*pItr)->IsAlive()) pItr = mParticles.erase(pItr);else ++pItr;}

But you should consider using the std::remove_if() algorithm and the erase() overload that takes an iterator range. It will likely be more efficient; removing elements from the middle of a vector is O(n) (think about how all the elements of the vector would have to be shuffled back one place to fill the 'gap').

Or you could keep the current algorithm and change to a std::list<>, in which case the removals will be O(1).

And it works it seems. Do anyone see a potential problem with this or should this be quite robust?

Also what is exactly the advantage of using iterators instead of just for (int i = 0; i < blablabla.size(); i++)? :)

Edit:the_edd: Thanks, I will look into using a std::list. I've never used it before but I'll read up on it :) I'm not sure if I understood the other option though (even if I remove a range of elements, wouldn't still the following elements have to be "moved"?)

(It should also be possible to make this easier with boost::bind, boost::lambda or something else along those lines.)

Quote:

(even if I remove a range of elements, wouldn't still the following elements have to be "moved"?)

There are no "following elements" with this approach.

Because the standard library algorithms work with iterators rather than containers, they can't resize the containers themselves; therefore, std::remove_if effectively leaves garbage at the end of the container. The vector .erase() call simply trims off all the garbage at once. (You could also .resize(), but you'd have to convert the iterator returned by remove_if to an element count, and that's kind of messy.)