Bitesize Modern C++ : Range-for loops

If you’re using container classes in your C++ code (and you probably should be, even if it’s just std::array) then one of the things you’re going to want to do (a lot) is iterate through the container accessing each member in turn.

Without resorting to STL algorithms we could use a for-loop to iterate through the container.

image

If the above is baffling to you there are plenty of useful little tutorials on the STL on the Internet (For example, this one)

We could simplify the iterator declaration in C++11 using auto:

image

(See the article on auto type-deduction for details of how it works)

However, there’s a nicer syntactic sugar to improve our code: the range-for loop:

image

The semantics of the range-for are: For every element in the container, v, create a reference to each element in turn, item.

The above code is semantically equivalent to the following:

image

Look familiar?

Not only does this save you some typing but, because it’s the compiler that’s generating the code it has a lot more potential for optimisation (for example, the compiler knows that the end() iterator is not invalidated in the body of the range-for statement, therefore it can be read once before the loop; or the compiler may choose to unroll the loop; etc.)

In case you were wondering, std::begin() and std::end() are free functions that return an iterator to the first element in the supplied container and an iterator to one-past-the-end, respectively. For most STL containers they simply call cont.begin() and cont.end(); but the functions are overloaded to handle built-in arrays and other container-like objects (see below)

Range-for loops are not limited to STL containers. They can also work with built-in arrays:

image

And also std::initializer_lists

image

More information

Can’t wait? Download the full set of articles as a PDF, here.

To learn more about Feabhas’ Modern C++ training courses, click here.

Glennan Carnie

Glennan Carnie

Technical Consultant at Feabhas Ltd
Glennan is an embedded systems and software engineer with over 20 years experience, mostly in high-integrity systems for the defence and aerospace industry.

He specialises in C++, UML, software modelling, Systems Engineering and process development.
Glennan Carnie

Latest posts by Glennan Carnie (see all)

Dislike (0)

About Glennan Carnie

Glennan is an embedded systems and software engineer with over 20 years experience, mostly in high-integrity systems for the defence and aerospace industry. He specialises in C++, UML, software modelling, Systems Engineering and process development.
This entry was posted in C/C++ Programming and tagged , , , , , , , . Bookmark the permalink.

5 Responses to Bitesize Modern C++ : Range-for loops

  1. Vincent says:

    Hi Glennan,

    Very nice post but I wondered why we would always have to pre-increment the iterator in the non inclusive loop ?

    I just tested myself and the behavior between post-increment and pre-increment seems the same.

    And if it is for an optimization purpose, do we really have to do this ? I mean, the compiler will fix it easily I suppose ?

    Like (0)
    Dislike (0)
  2. Matt says:

    Hi, that's actually not quite correct - the ranged-for loop is semantically equivalent to:

    for (auto it = std::begin(r), end = std::end(r); it != end; ++it) {
    auto &item(*it);
    ...
    }

    So the end iterator is evaluated only before the loop.

    See: http://en.cppreference.com/w/cpp/language/range-for

    Like (0)
    Dislike (0)
  3. Ivan Čukić says:

    One issue - in your 'unwrapped' version of the range-for loop, std::end is called on every iteration which is not the case.

    Both begin and end are called only on initialization.

    Lets hope this gets rendered properly:

    auto && __range = range_expression;
    for (auto __begin = begin_expr,
    __end = end_expr;
    __begin != __end; ++__begin)
    {
    range_declaration = *__begin;
    loop_statement
    }

    Like (0)
    Dislike (0)
  4. Matt,

    Good catch. I've updated the original post to reflect this.

    Thanks!

    Like (0)
    Dislike (0)
  5. Ivan,

    I've updated the post to reflect this.

    Thanks!

    Like (0)
    Dislike (0)

Leave a Reply