Learning C++11 (Part 2)

range-based for

This is C++11's answer to foreach which you see in a lot of scripting languages. Much like auto, it simplifies the sometimes verbose syntax of a standard for-loop. It's great when you just need the value of what you're iterating over.

You can use range-based for on your collection classes if begin() and end() are implemented as well as plain C arrays. Let's look at some examples.

Old C++

  for (std::vector<int>::const_iterator itr = v.cbegin(); itr != v.cend(); ++itr)
  {
    auto value = *itr;
    printf("value: %d\n", value);
  }

  for (int i = 0; i < v.size(); ++i)
  {
    int value = v[i];
    printf("value: %d\n", value);
  }

C++11

  for (auto value: v)
  {
    printf("value: %d\n", value);
  }

Simple example of iterating over a container and printing the results. Two different ways of doing it the old way, but both can be simplified the same way in C++11. The code is greatly simplified to only what we care about (the value) and nothing else.

Old C++

  for (std::vector<int>::iterator itr = v.begin(); itr != v.end(); ++itr)
  {
    *itr *= 2;
  }

C++11

  for (auto& value: v)
  {
    value *= 2;
  }

This time we want to modify each entry in the container. Note in this example we need to use a reference in the range-based for.

When to use value vs. reference

Here are some general rules on when to use value or reference. * When you want to change the value, use a reference (auto&) * When the value would incur a copying penalty, use a const reference (const auto&) * Otherwise, simply use by value (auto)

There's something missing

Remember the first example where we used the index to get the value out of the vector? When you use range-based for you lose that index or iterator if you need it for something else.

-- Garner Halloran (Engine Programmer)