[C++] Erasing std::map::iterators while walking the container [solved]

Started by
10 comments, last by Decrius 14 years, 11 months ago
Not too surprisingly the following code is crashing the executable:
        std::map<unsigned int, unsigned int>::iterator iterator;
        for (iterator = access.begin(); iterator != access.end(); ++iterator)
        {
            access.erase((*iterator).first); // of course, the actual code is not this simple
        }

I'm afraid I have this multiple times in my code, also for vectors. Is this code just as dangerous for vectors as well? Also, what would be a better way of doing this? Should I remember the last iterator, then go to the next, and then erase the remembered iterator? Thanks! [Edited by - Decrius on May 19, 2009 1:55:31 AM]
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora
Advertisement
For your code sample, you'd call std::map<>::clear().

If you want to conditionally erase iterators in an associative container you'd use:
for (iter = map.begin(); iter != map.end();) {  if (condition(iter)) container.erase(iter++);  else ++iter;}
Again, thanks SiCrane ;)

Does this apply to vectors too, or is it harmless for vectors?
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora
Vectors you would use generally use the erase-remove idiom. If for some reason you had to manually loop you'd use:
for (iter = vec.begin(); iter != vec.end();) {  if (condition(iter)) iter = vec.erase(iter);  else ++iter;}
Okay thanks, I guess you meant:

for (iter = vec.begin(); iter != vec.end();) {  if (condition(iter)) iter = vec.erase(iter++);  else ++iter;}


But I get the point, same as maps that is. Thanks.
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora
No, I didn't. The two loops are different.
Quote:Original post by SiCrane
No, I didn't. The two loops are different.


Oops, just noticed ^^.
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora
Quote:Original post by SiCrane
Vectors you would use generally use the erase-remove idiom. If for some reason you had to manually loop you'd use:
for (iter = vec.begin(); iter != vec.end();) {  if (condition(iter)) iter = vec.erase(iter);  else ++iter;}


Hmmm... Wouldn't that cost O(n^2) time? What I have typically done is
for (read_iter = vec.begin(), write_iter = vec.begin(); read_iter != vec.end(); ++read_iter) {  if (!condition(read_iter)) {    *write_iter = *read_iter;    ++write_iter;  }}vec.resize(write_iter-vec.begin());

And that is why I said you should generally use the erase-remove idiom.
Ah I see, is that because erase() makes the std::map reorder it's elements? And, wouldn't swapping elements of the std::map break the algorithm it uses to find elements?

Also, doesn't this remove-erase idiom make me copy the values hold by the std::map a lot of times? Hmm, or does std::swap not actually use the copy constructor / assignment operator?
[size="2"]SignatureShuffle: [size="2"]Random signature images on fora

This topic is closed to new replies.

Advertisement