Default constructed map iterator enters infinite loop on increment - Green Hills compiler

596 views Asked by At

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?

1

There are 1 answers

6
463035818_is_not_an_ai On BEST ANSWER

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.