Range-based for loop (since C++11)
Executes a for loop over a range.
Used as a more readable equivalent to the traditional for loop operating over a range of values, such as all elements in a container.
Syntax
attr(optional) for ( range_declaration : range_expression ) loop_statement
|
|||||||||
attr | - | any number of attributes |
range_declaration | - | a declaration of a named variable, whose type is the type of the element of the sequence represented by range_expression, or a reference to that type. Often uses the auto specifier for automatic type deduction |
range_expression | - | any expression that represents a suitable sequence (either an array or an object for which begin and end member functions or free functions are defined, see below) or a braced-init-list.
|
loop_statement | - | any statement, typically a compound statement, which is the body of the loop |
range_declaration may be a structured binding declaration for (auto&& [first,second] : mymap) { // use first and second } |
(since C++17) |
Explanation
The above syntax produces code equivalent to the following (__range
, __begin
and __end
are for exposition only):
|
(until C++17) | |||||||||||||||||||||||
|
(since C++17) |
range_expression is evaluated to determine the sequence or range to iterate. Each element of the sequence, in turn, is dereferenced and assigned to the variable with the type and name given in range_declaration.
begin_expr
and end_expr
are defined as follows:
- If range_expression is an expression of array type, then
begin_expr
is __range andend_expr
is (__range + __bound), where__bound
is the number of elements in the array (if the array has unknown size or is of an incomplete type, the program is ill-formed) - If range_expression is an expression of a class type
C
that has a member named begin and/or a member named end (regardless of the type or accessibility of such member), thenbegin_expr
is __range.begin() andend_expr
is __range.end(); - Otherwise,
begin_expr
is begin(__range) andend_expr
is end(__range), which are found via argument-dependent lookup (non-ADL lookup is not performed).
If range_expression returns a temporary, its lifetime is extended until the end of the loop, as indicated by binding to the rvalue reference __range
, but beware that the lifetime of any temporary within range_expression is not extended.
Just as with a traditional loop, a break statement can be used to exit the loop early and a continue statement can be used to restart the loop with the next element.
attr represents an optional number of attributes.
Notes
If the initializer (range_expression) is a braced-init-list, __range is deduced to be std::initializer_list<>&&
It is safe, and in fact, preferable in generic code, to use deduction to forwarding reference, for (auto&& var : sequence).
The presence of any member named begin
or end
, regardless of whether it is a type, data member, function, or enumerator, and regardless of its accessibility, will cause __range.begin() and __range.end() to be used as begin_expr
and end_expr
, respectively. As a result, the range-based for loop cannot be used with classes containing member types or enumerators named begin
or end
even if the appropriate namespace-scope free functions are provided.
While the variable declared in the range_declaration is usually used in the loop_statement, doing so is not required.
As of C++17, the types of the begin-expression and the end-expression do not have to be the same, and in fact the type of the end-expression does not have to be an iterator: it just needs to be able to be compared for inequality with one. This makes it possible to delimit a range by a predicate (e.g. "the iterator points at a null character").
Keywords
Example
#include <iostream> #include <vector> int main() { std::vector<int> v = {0, 1, 2, 3, 4, 5}; for (const int& i : v) // access by const reference std::cout << i << ' '; std::cout << '\n'; for (auto i : v) // access by value, the type of i is int std::cout << i << ' '; std::cout << '\n'; for (auto&& i : v) // access by reference, the type of i is int& std::cout << i << ' '; std::cout << '\n'; for (int n : {0, 1, 2, 3, 4, 5}) // the initializer may be a braced-init-list std::cout << n << ' '; std::cout << '\n'; int a[] = {0, 1, 2, 3, 4, 5}; for (int n : a) // the initializer may be an array std::cout << n << ' '; std::cout << '\n'; for (int n : a) std::cout << 1 << ' '; // the loop variable need not be used std::cout << '\n'; }
Output:
0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 0 1 2 3 4 5 1 1 1 1 1 1
See also
applies a function to a range of elements (function template) |