Confused use of STL C ++ iterator

Although I use an iterator like this,

//include header files using namespace std; int main() { map<int,int> intIntMap; map<int,int>::iterator pos; pos = intIntMap.begin(); intIntMap[0] = 1; intIntMap[3] = 5; intIntMap[4] = 9; intIntMap[5] = 5; //้ๅކ cout << (*pos).first << endl; while( pos != intIntMap.end() ) { cout << pos->first << " <---> " << pos->second << endl; pos++; } } 

The output signal is 4;

But for now, I'm using an iterator like this:

 //include header file using namespace std; int main() { map<int,int> intIntMap; map<int,int>::iterator pos; intIntMap[0] = 1; intIntMap[3] = 5; intIntMap[4] = 9; intIntMap[5] = 5; //้ๅކpos = intIntMap.begin(); cout << (*pos).first << endl; while( pos != intIntMap.end() ) { cout << pos->first << " <---> " << pos->second << endl; pos++; } } 

The result is what I want;

I want to know what is the difference between using an iterator, what happened to the first iterator when inserting a new key-value pair? Thanks!

addtion: the compiler uses gcc 4.1.2, feeling more confused, for example:

compile is use gcc 4.1.2, in feel more confused, like this:

+4
source share
5 answers

Since you called begin() when the container was empty, you got an iterator equal to end() (ยง23.1 / 7: "If the container is empty, then begin () == end ()").

The insertion of elements into the container has not changed, so you still have pos == intIntMap.end() .

Then you do iteration zero of your loop, since pos==end() , and you only loop until pos != end() .

In the second example, you set pos() after you have inserted the data, so that you get the first elements in the collection and move on to the last.

Change As for listing the contents of the card, I would most likely do it as follows:

 std::ostream &operator<<(std::ostream &os, std::pair<int, int> const &d) { return os << d.first << " <---> " << d.second; } // ... std::copy(intIntMap.begin(), intIntMap.end(), std::ostream_iterator<std::pair<int, int> >(std::cout, "\n")); 
+10
source

After going through gdb, I found that the first field of the iterator changed with each addition of the key-value pair. It seems that the iterator to the map without data in it (returned by begin() ) contains some metadata about the map itself, in particular the size of the map (the first field of the specified iterator increased with each addition of the key - a significant pair). Calling begin() to retrieve the iterator after adding one key-value pair leads to the "expected" behavior.

+2
source

Iterators are intended for use in a container that has not been modified since the creation of the iterator. The code output in the first example is undefined, in accordance with the C ++ standard (you can still get the desired result, you are simply not guaranteed to get it, and there are not many reasons to expect it).

In the first case, nothing happened with the iterator, but the container that you intend to view it has undergone changes and is not necessarily located in one place in memory.

-1
source

Modifying the container invalidates existing iterators.

A common practice is to get an iterator just before using it, and then throw it away. You can use for as follows:

 #include <iostream> #include <map> using namespace std; int main () { map<int, int> mymap; mymap[0] = 100; mymap[1] = 200; mymap[2] = 300; // show content: for (map<int, int>::iterator it = mymap.begin(); it != mymap.end(); it++) cout << (*it).first << " => " << (*it).second << endl; return 0; } 
-1
source

Short answer: there is no guarantee that the iterator remains valid after changing the contents of the container.

Since the container map here, usually implemented as a red-black tree, the structure changes and is rebalanced during insertion.

In the first example, you initialize the pos iterator before the start of the map. At this point, the iterator is valid for the current content. But as soon as you start adding items, the iterator no longer points to the new begin position of the reorganized container.

So, the reason the second example works is because you set the iterator to begin after all the changes in the container are complete.

In general, it is a bad idea to change the structure, iterate over it.

There is more information on the validity of iterators in this question:

-1
source

All Articles