16.3 — STL iterators overview

An Iterator is an object that can traverse (iterate over) a container class without the user having to know how the container is implemented. With many classes (particularly lists and the associative classes), iterators are the primary way elements of these classes are accessed.

An iterator is best visualized as a pointer to a given element in the container, with a set of overloaded operators to provide a set of well-defined functions:

  • Operator* -- Dereferencing the iterator returns the element that the iterator is currently pointing at.
  • Operator++ -- Moves the iterator to the next element in the container. Most iterators also provide Operator-- to move to the previous element.
  • Operator== and Operator!= -- Basic comparison operators to determine if two iterators point to the same element. To compare the values that two iterators are pointing at, dereference the iterators first, and then use a comparison operator.
  • Operator= -- Assign the iterator to a new position (typically the start or end of the container’s elements). To assign the value of the element the iterator is pointing at, dereference the iterator first, then use the assign operator.

Each container includes four basic member functions for use with Operator=:

  • begin() returns an iterator representing the beginning of the elements in the container.
  • end() returns an iterator representing the element just past the end of the elements.
  • cbegin() returns a const (read-only) iterator representing the beginning of the elements in the container.
  • cend() returns a const (read-only) iterator representing the element just past the end of the elements.

It might seem weird that end() doesn’t point to the last element in the list, but this is done primarily to make looping easy: iterating over the elements can continue until the iterator reaches end(), and then you know you’re done.

Finally, all containers provide (at least) two types of iterators:

  • container::iterator provides a read/write iterator
  • container::const_iterator provides a read-only iterator

Lets take a look at some examples of using iterators.

Iterating through a vector

This prints the following:

0 1 2 3 4 5

Iterating through a list

Now let’s do the same thing with a list:

This prints:

0 1 2 3 4 5

Note the code is almost identical to the vector case, even though vectors and lists have almost completely different internal implementations!

Iterating through a set

In the following example, we’re going to create a set from 6 numbers and use an iterator to print the values in the set:

This program produces the following result:

-6 -4 1 2 7 8

Note that although populating the set differs from the way we populate the vector and list, the code used to iterate through the elements of the set was essentially identical.

Iterating through a map

This one is a little trickier. Maps and multimaps take pairs of elements (defined as a std::pair). We use the make_pair() helper function to easily create pairs. std::pair allows access to the elements of the pair via the first and second members. In our map, we use first as the key, and second as the value.

This program produces the result:

1=banana 2=orange 3=grapes 4=apple 5=peach 6=mango

Notice here how easy iterators make it to step through each of the elements of the container. You don’t have to care at all how map stores its data!


Iterators provide an easy way to step through the elements of a container class without having to understand how the container class is implemented. When combined with STL’s algorithms and the member functions of the container classes, iterators become even more powerful. In the next lesson, you’ll see an example of using an iterator to insert elements into a list (which doesn’t provide an overloaded operator[] to access its elements directly).

One point worth noting: Iterators must be implemented on a per-class basis, because the iterator does need to know how a class is implemented. Thus iterators are always tied to specific container classes.

16.4 -- STL algorithms overview
16.2 -- STL containers overview

70 comments to 16.3 — STL iterators overview

  • Anthony

    First, a couple of really good Stack Overflow answers on creating your own iterators:

    Second, a question about the typedefs (yes, we should use 'using' instead) in the following:

    Is typedef #2 shadowing typedef #1? Or, put another way, would typedef #1 be available where typedef #2 is if typedef #2 wasn't there? Or again, is #2 strictly necessary?

    -- Anthony

    • `iterator` can see everything inside of `X`, you don't need to re-define types.

      • Anthony

        Excellent. Thank you. And like Columbo says: "Oh, just one more thing, sir, if I may.."

        I'm pretty sure I have most of the operator overloads correctly defined in my STL-style ring buffer random-access iterator. Elements of the buffer are accessed via a private member integral index called @offset_. However, I am unable to find good documentation on a few of the overloads (there are so many pages out there with incomplete and contradictory information). I believe the following six are properly declared (they adhere to those Stack Overflow answers I mentioned earlier in this thread), but I am uncertain how five of the six should be defined:

        I feel so guilty about asking, but.. oh well.

        • I wrote this answer for `offset_` being an arbitrary type/pointer before I realized it's an integer. The answers apply to an integer, so I'll just keep it this way.

          Line 1
          Assuming you mean this alternative

          No. You only need this if `offset_` doesn't support `operator+=`, eg. because it's a linked list. If `offset_` supports `operator+=`, use it.

          Line 6
          Same as line 1.

          Line 11 and 15
          Create new iterators `n` elements past the current iterator.

          Line 19
          Same as line 11 and 15.
          Here the reverse doesn't make sense, so you only have `it - 5`.

          Line 23
          If `offset_` is a pointer, only correct if `it1.offset_` and `it2.offset_` are pointers into the same array.
          Correct if `offset_` is an integer.

  • Spirit

    "element the iterator is point at, dereference" Shan't it be "is pointing"?

  • Danty Wong

    So I wanted to practice my C++ template and decided to use a templated function to print out elements of each of the container above.
    On line 19 and 32 where the iterators are declared, the keyword 'typename' is required for the code to compile. Can somebody please explain what this means?

    Also, am I missing something in chapter 13? I don't recall a tutorial on templated container class as template argument.


    • Hi!

      * Line 37, 42: Initialize your variables with brace initializers. You used copy initialization.
      * Line 11, 12, 24, 25, 57: Initialize your variables with brace initializers.
      * Line 28: Limit your lines to 80 characters in length for better readability on small displays.

      I assume you mean line 11 and 24. Those are required to tell the compiler that @const_iterator is a type, not a static member, as those use the same syntax.

  • Jon

    Hello! A few quick questions for you...

    During my studies I've heard people say "list", "linked list", and "doubly-linked list". Are these all just different names for std::list?

    Also, in real life would you use a ranged for-loop instead of an iterator to do the kinds of printing tasks in these examples?
    Is one more efficient than the other?

    Thank you!

    • Alex

      Normally people use "list" and "linked list" interchangeably, with "doubly-linked list" being slightly different. Linked lists and doubly-linked lists are generic data structures. std::list is one implementation of such a data structure -- usually as a double-linked list.

      I prefer to use ranged-for whenever possible, as the syntax is easier than the iterator syntax. However, iterators are more flexible, as they give you control over when the iterator moves, and whether you're iterating forwards or backwards.

  • I see that you are <using namespace std> a lot in the examples here but we have been told to avoid using namespaces for a long while now - is there a reason for this?

    Also, off topic now, is it possible to use XML or HTML to create a GUI and then use C++ for "code behind" to handle the controls and other events as one can when using C#?

    • As always, GUI is OS-specific and has nothing to do with the language, apart from the bindings. You'll have to write a parser/converted on your own or use a GUI framework that ships with the capabilities you want.
      Qt can load XML layouts (Example file ). I dislike Qt, because they require you to use their compiler with non-standard language extensions. But it's the only one I know of.

    • Alex

      The only reason is because the lessons in this chapter are long overdue for an update. I'll put it on my to-do to do a quick pass for this chapter at least.

  • excalibur

    what is the advantage of using iterators over pointers?

    • Alex

      Iterators allow you to traverse a series of values without having to know anything about the details of how the container holding those values is implemented (it may not even use pointers).

  • Lamont Peterson


    In the operator= part, I think you meant "dereference" instead of "deference".

  • C++ Learner

    how we can assign value to read only iterator? can you exlain what read only means? the name is confusing a little bit

  • Hi,
    I just remembered a doubt I've had from before. Does it matter if you call a function in the loop's condition or use a variable? For example:


    In this case, does it make a difference if we call li.End() directly or store it in a variable and then use it? Because in my mind, I think that if I store it as a variable, it will just call the function once and then simply use the variable's value for subsequent condition evaluations (which should be faster) but if I don't store it in a variable, it's gonna keep calling the function every time the loop has to evaluate the condition.
    Thanks a lot!

  • Anonymous

    Hi, I was once asked a question in an interview "what is the difference/similarity between an iterator and a pointer"...I replied "a pointer is an iterator because it can be used to traverse a list/array"..However, can you please help/elaborate in answering this question? Thank you!

    • Alex

      A pointer is simply a variable that holds an address. An iterator is an object that is used to traverse a container. Iterators are generally implemented using pointers. So they're related, in that one can be implemented using the other, but iterators are more for a specific purpose whereas pointers are more general.

  • Bishal Imtiaz

    using namespace std;
    int main()
        int n;
        vector<int> v;
        for(int i=0;i<n;i++)
            int x;

        for(vector<int>::iterator it=v.end();it!=v.begin();it--)
            cout<<*it<<" ";

    output:"garbage" 5 4 3 2 instead of 5 4 3 2 1

    • Alex

      end() is one past the end of the vector.

      If you want to walk through the vector in reverse, you should iterate from rbegin() to rend() and use operator++.

  • john

    Is this a good place to use the keyword "auto"? For example:

  • Ninja

    Hey Alex, so I'm sort of confused about Iterators. I know what they are and how to use them. But when you use ::iterator, what does that mean? Are you accessing a static object called iterator that is in every container class? or is iterator a separate class that is being used by the container class (like association)?

    Another thing I was confused about is when you use it->first and it->second. So does that mean first and second are public members variables of std::pair? Also, I did my maps in a different way than yours, is there anything wrong with it? I used a for loop instead of a while for everything and try_emplace instead of insert for maps, is that okay?

    • Alex

      Iterators in the standard library are generally implemented as nested classes, therefore, when you see something like std::vector::iterator, we're accessing the iterator class that's nested inside of std::vector. This isn't a static object -- it's a class definition that just happens to be defined inside another class. That way, std::vector::iterator and std::map::iterator can have different implementations but both be called "iterator".

      std::pair is implemented as a struct, and as such its members (which are named first and second) are publicly accessible.

      There's nothing wrong that I can see with what you've done. insert will insert duplicate values (which isn't an issue here), whereas try_emplace won't. And which type of loop you use (while vs do while vs for) is more often a matter of personal choice and comfort than anything else.

  • CitizenX

    Ok, so here's what I got so far. Now, given that this is a _total_ hackjob, and probably not as well thought through as it could be (at the moment, I am working on it), it works over a concatenation of two containers, vector, deque, list so on, but not on two different containers, which is what I ultimately want. After doing some searching on the internet, I've come to realize that maybe I need to use PIMPL as idiom for the iterator, to be able to iterate over different containers, meaning one interface, holding a pointer to a baseclass, which gets derived into the implementation (if i'm not mistaken, this is what that basically would mean).

    Anyway, this works so far, and any input would be greatly appreciated.

    So basically, what I'm after here, is a container, holding two containers of the same value_type.

  • CitizenX

    Hi, is there any where I can get help/read up on how to create a multi-iterator? (and I need to learn, the concepts around it, so just saying "use boost" is not going to cut it, for me) By that I mean, kind of a iterator which you can use with STL algorithms, such that,

    woud produce the output: 1 , 2 , 3 , 4 , 5 , 6
    so.. here’s what I’ve come up with so far;

    But I get stuck here… am I on the right path? Any help appreciated.

    • Alex

      I'd have to think about this a lot more (and probably do a lot of experimentation myself) to say what the best way to do this would be, so I don't think I can be of much help here. My advice would be that what you're doing looks overcomplicated. I'd probably start by removing the templating and all of the complexity around pointer and reference types, and focus on making it work for with just std::vector<int>::iterator. Once you have that working, then you can figure out how to broaden this out to work with other iterator types.

  • Matt

    In your last code example, under "Iterating through a map", you wrote:
    cout << it->first << "=" << it->second << " ";

    Since "first" and "second" are member functions, don't they need to have parentheses at the end?

    • Alex

      No, first and second are not member functions. They're members of the pair. You can access them directly.

      • Matt

        I'm still confused about this, because in the paragraph above this code example, you characterize first and second as member functions:
        " std::pair allows access to the elements of the pair via the first() and second() member functions. In our map, we use first() as the key, and second() as the value."

        • Alex

          My mistake -- they aren't functions, they're just normal members. I've updated the lesson accordingly.

          Basically, std::pair looks something like this:

  • Matt

    In the code under "Iterating through a vector", in the first comment, "an" should be "a".

  • Darren

    Interesting, you use while loops to iterate through containers. **While** you are entitled to your opinion, **for** that I much prefer for loops.

    Also what about the keyword 'auto' (c++11 onwards)? Could save on a lot of typing!

    • Dani

      For the second, I'd say yes. I thought the same and tried it, here's my approach

      I'ce there's any downside of using it this way, I've missed it

  • SJ

    Maybe you could briefly talk about rbegin() and rend() as well.

  • Mekacher Anis

    does this mean that iterators belong to classes ?

  • Reaversword

    How its possible to use "const_iterator" (that I understand, it's a constant, and thereby, it can't change), and even being constant, it remains being possible to cycle it with ++ or --?.

    I can understand when you make the FIRST "++" or "--", you're pointing to the "next" or "previous" memory address (as temporary address, since iterator is constant and cannot change), but not why this works for next iterations. If iterator pointer is constant, I understand the iterator should be using something like "iterator+n". But despite of to be constant, I see clearly not to be "read only".

    So, in which sense "const_iterator" is really constant?. It is just about you can't change iterator directly assigning it a position? (const_iterator = 3)?.

    • Alex

      A const_iterator isn't constant itself. Rather, it treats the values it is iterating over as const (and returns a const reference to them, instead of a normal reference).

      Thus, a const_iterator is a good choice when you want a read-only iterator, because it will prevent you from changing the values you are iterating over.

  • Matt

    Found some typos:
    * "Operator-" should be "Operator--" (two hyphens): "Most iterators also provide Operator- to move to the previous element."
    * "stl" should be "std": "(defined as an stl::pair)"
    * "it's" should be "its": "(which doesn’t provide an overloaded operator[] to access it’s elements directly)"

  • Stas

    I think you made a small typo in the conclusion, I'm still new to C++ but I just want to clarify. You wrote, "Iterators provide an easy way to step through the elements of a container class without having to understand how the container class is implemented.", and a bit after this you write, "the iterator does need to know how a class is implemented".

    Isn't this a contradiction or am I under-informed on the vocab you're using? Thanks in advance.

    • Alex

      Let me use an analogy here. You don't have to know how your TV is built to use a TV remote, but your TV remote does need to know how the TV is built in order to send a command to it.

      You don't need to know how a class is implemented to use an iterator, but the iterator does need to know how the class is implemented to iterate through it.

      Make sense?

  • Marek

    When moving iterator to next element, pre-increment should be preferred, it's more efficient on iterators.

  • tata

    Somehow the syntax below appears to be asking for a static member variable called const_iterator; but const_iterator is obviously not a member variable, but the name of a type/class.

    If we've previously seen the scope operator used this way, could someone help point out the chapter, thanks (is it that const_iterator is a class defined in the namespace of vector?)

    A quick google has yet to produce accessible material that explains away this use of the scope operator; I'm most likely forgetting and missing something simple

    • tata

      It appears that this is an example of nested classes described here:

      If this is wrong, please correct me

    • Alex

      This version of const_iterator is a typedef defined in the public part of std::vector, so yes, const_iterator is essentially in the namespace of class std::vector.

  • foobar

    "Most iterators also provide Operator- to move to the previous element." => Operator-- ?

    Edit: I see. I entered Operator dash dash and it is displayed as Operator dash. Weird.

  • Anthony

    How does the List version work?

    while (it != li.end())

    li.end is not efficient in a linked list.

    The whole iterator seems completely wrong. It should be

    while (!it.end())

    Too much C hackery in the design.

  • Neha Kumari


    Which is better List or Vector? And when to use list and when to use vector?

    • Alex

      It really depends on the needs of your application.

      If you need random access to elements, probably Vector. If you need to insert a lot of elements and don't need random access to the elements, probably List.

  • abhishekp

    Just to add, We may insert element in map by directly giving it's index. for example in the above mentioned program mymap[6]="mango"; rather than to use mymap.insert(make_pair(6, "mango"));

  • maalika

    Under "Iterating through a map" section, did you mean std:: pair instead of "stl::pair"? May be just a typo? Or does it mean, STL?

Leave a Comment

Put all code inside code tags: [code]your code here[/code]