Namespaces
Variants
Actions

Difference between revisions of "intro/range for"

From cppreference.com
(let's not lose this (import from intro/control/for))
 
(colon/semicolon typo)
Line 14: Line 14:
  
 
{{source|1=
 
{{source|1=
for (auto p = container.begin(); p != container.end(): ++p) {
+
for (auto p = container.begin(); p != container.end(); ++p) {
 
     /* variable declaration */ = *p;
 
     /* variable declaration */ = *p;
 
     // statements
 
     // statements
Line 23: Line 23:
  
 
{{source|1=
 
{{source|1=
for (int n = 0; n != sizeof(array): ++n) {
+
for (int n = 0; n != sizeof(array); ++n) {
 
     /* variable declaration */ = array[n];
 
     /* variable declaration */ = array[n];
 
     // statements
 
     // statements

Revision as of 23:30, 22 September 2013

The range-based for statement

The range-based for statement is a simpler and safer way to loop over the contents of a container or array.

It looks like this:

for (/* variable declaration */ : /* container or array */) {
    // statements
}

Which, for a container, expands to:

for (auto p = container.begin(); p != container.end(); ++p) {
    /* variable declaration */ = *p;
    // statements
}

For an array it expands to:

for (int n = 0; n != sizeof(array); ++n) {
    /* variable declaration */ = array[n];
    // statements
}

Normally you would use a variable declaration with auto, or possibly const auto&:

for (auto item : items) {
    // statements
}

If you don't use auto, the values in the container or array must be convertible to whatever type you use.

For example:

#include <iostream>
#include <string>
#include <vector>
 
int main()
{
    std::vector<std::string> doctors = { "Strange", "Octopus", "Who" };
 
    // You could use "std::string" instead of "auto"
    for (auto const& doc : doctors) {
        std::cout << "Paging Dr. " << doc << '\n';
    }
}

Output:

Paging Dr. Strange
Paging Dr. Octopus
Paging Dr. Who

If you use a non-const reference, you can change the values in the container or array within the loop:

For example:

#include <iostream>
#include <vector>
 
int main()
{
    int numbers[] = { 1, 2, 3, 4 };
 
    // Print numbers
    for (auto n : numbers)
        std::cout << n << ' ';
 
    // Double each number
    for (auto& n : numbers)
        n *= 2;
 
    std::cout << '\n';
 
    // Print numbers
    for (auto n : numbers)
        std::cout << n << ' ';
}

Output:

1 2 3 4 
2 4 6 8

The range-based for statement is not only easier to write, it is safer. You cannot accidently go past the end of a container or array, or make other mistakes like this:

std::vector<int> c1 = { 1, 2, 3 };
std::vector<int> c2 = { 4, 5, 6 };
 
// Mixing the begin/end from c1 and c2 by accident!
// This causes undefined behaviour!
for (auto p = c1.begin(); p != c2.end(); ++p) {
    std::cout << *p << '\n';
}

On the other hand, the range-based for statement is more limited. You can't start half-way through the sequence, and you can't advance by more than one item at a time. You can keep track of where you are in the sequence, but it requires an extra variable. (And of course, you can always end before the end of the sequence with a break statement.)