Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confused use of c++ STL iterator

Tags:

c++

iterator

stl

While I use 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 is 4;

But while I use 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 output is what I want;

I want to know what is the difference between use of iterator, what happended to the first iterator when I insert new key-value pair ? Thanks!

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

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

like image 551
Sprout_Wang Avatar asked Jan 16 '23 07:01

Sprout_Wang


2 Answers

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

Inserting items into the container didn't change that, so you still have pos == intIntMap.end().

You then execute zero iterations of your loop, since pos==end(), and you'r executing the loop only as long as pos != end().

In the second example, you set pos() after you've inserted the data, so you get the first items in the collection, and iterate to the last.

Edit: As far as printing out the contents of the map goes, I'd probably do it more like this:

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"));
like image 68
Jerry Coffin Avatar answered Jan 22 '23 07:01

Jerry Coffin


Going through this with gdb, I found that the first field of the iterator was changing with each addition of a key-value pair. It seems that an iterator to a map with no data in it (returned by begin()) contains some metadata about the map itself, specifically the size of the map (the first field of said iterator grew with each addition of a key-value pair). Calling begin() to retrieve the iterator after a single key-value pair is added results in the "expected" behavior.

like image 20
eqzx Avatar answered Jan 22 '23 09:01

eqzx