I have to do a trivial iteration of all the elements in a std::map, first to last. On each element I have to perform an operation. Assume that the map contains the following pairs:
map<string,string> farm={
{"one","puppy"},
{"two","kitty"},
{"three","sheepy"}
}
The bit of code that performs the iteration is the following:
for(map<string,string>::iterator beast; beast!=farm.end(); ++beast)
{
feed(*beast);
}
Now the surprise is that the above code works for the first element (puppy
is fed) but the iterator fails to go to the next elements. The debugger shows that ++beast
never returns (seems like it is recursively branching on its left leaf forever).
It seems that the issue here is that beast
is never assigned to farm.begin()
and as such it can't progress to the next item (see first element of the for).
So here are my questions:
Is it normal that the default constructor of a map iterator automatically positions the object to point to the map.begin()
element?
If that is common practice, then why a valid first element is
returned (it could have been returned map.end()
for example) ?
How could the operator++
be allowed to quietly fail in an infinite loop? Wouldn't be better to return with an error code (we disabled
exceptions) or fail openly somehow ?
I wonder if the standard allows this kind of behaviours or it is an implementation choice.
Assumptions: I am not using C++11, I am using Green Hills compiler v2016 with execption support disabled
EDIT:
I am trying to understand why I get a valid value and a quiet fail as in other threads people suggest that a default-constructed iterator is assigned to map.end()
. Does the standard gives guidance on this?
Is it normal that the default constructor of a map iterator automatically positions the object to point to the map.begin() element?
No, you should initialize it properly:
for(map<string,string>::iterator beast = farm.begin(); beast!=farm.end(); ++beast)
Btw there is no way that the compiler can know that you want map<string,string>::iterator beast
to be an iterator for farm
, of course you need to get an iterator from the container and not just create an iterator and assume it points to the container you wish.