std::map iteration safety

N

neilsolent

Hi

Is it valid to iterate over a std::map like this:

//////////////

map<string, msg*>::iterator it;

for (it = m_myMap.begin(); it != m_myMap.end(); it++)
(*it).second->Check();

////////////////

... where the function Check() may add or remove elements from m_myMap.

I am worried that this may cause a crash. Should I make a copy of
m_myMap first ?

thanks
Neil
 
K

Kai-Uwe Bux

neilsolent said:
Is it valid to iterate over a std::map like this:

//////////////

map<string, msg*>::iterator it;

for (it = m_myMap.begin(); it != m_myMap.end(); it++)
(*it).second->Check();

////////////////

.. where the function Check() may add or remove elements from m_myMap.

I am worried that this may cause a crash. Should I make a copy of m_myMap
first ?

Your program will have undefined behavior when and only when Check() removes
the item that the iterator it identifies. This is a consequence of std::map
being an associative container: erase only invalidates iterators pointing
to the removed element.

When Check() inserts items, those whose key are behind it->first will be
visited in the loop, those inserted before won't. Whether that is what you
want, I cannot say.


Best

Kai-Uwe Bux
 
N

neilsolent

Hi Kai-Uwe

Thanks for the reply.
Your program will have undefined behavior when and only when Check() removes
the item that the iterator it identifies. This is a consequence of std::map
being an associative container: erase only invalidates iterators pointing
to the removed element.

If the item that "it" points at is removed - the loop next runs "it++"
- I guess that's where the problem is?
I will check my code to see if the current item can ever get deleted
by Check(), and if so find another way.
When Check() inserts items, those whose key are behind it->first will be
visited in the loop, those inserted before won't. Whether that is what you
want, I cannot say.

That behaviour is fine for my app, and I expected as much.
 
K

Kai-Uwe Bux

neilsolent said:
Hi Kai-Uwe

Thanks for the reply.


If the item that "it" points at is removed - the loop next runs "it++"
- I guess that's where the problem is?

Yes.

More generally, any operation involving an invalid iterator yields undefined
behavior. That goes for dereferencing as well. Thus, if you increment the
iterator before the call to Check(), you just might get the same problem in
the next iteration (if Check() happens to remove the item behind the
current one).


Best

Kai-Uwe Bux
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top