A range-basedDocumentation Index
Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
Use this file to discover all available pages before exploring further.
for loop is a C++11 language construct that provides a simplified syntax for iterating over elements of a container or any range defined by begin() and end() iterators. It acts as syntactic sugar, abstracting away explicit iterator management and index manipulation by operating directly on the dereferenced elements yielded by the range expression.
Syntax
init-statement_opt(Optional, introduced in C++20): A declaration or expression that initializes variables scoped to the lifetime of the loop. In C++ grammar, aninit-statementinherently includes its terminating semicolon (e.g.,int i = 0;).range_declaration: A declaration of a named variable. The type of this variable is deduced from the elements of the sequence, typically utilizingautocombined with reference (&,&&) andconstqualifiers.range_expression: An expression that evaluates to a sequence. This can be a braced-init-list, a built-in array, or an object of a type that exposesbegin()andend()iterators (either as member functions or via Argument-Dependent Lookup).loop_statement: The body of the loop executed for each element.
Compiler Expansion
The C++ standard dictates that the compiler expands the range-basedfor loop into an equivalent traditional for loop.
A standard range-based for loop translates to the following underlying structure:
__begin and __end are allowed to differ, enabling compatibility with sentinel values used in ranges.
Resolution of begin_expr and end_expr
The compiler resolves the iterators based on the type of __range:
- Built-in Arrays: If
__rangeis an array of known bound, it resolves to pointers to the first element and one past the last element (__rangeand__range + bound). - Member Functions: If
__rangeis a class type possessing.begin()and.end()member functions, it resolves to__range.begin()and__range.end(). - Non-Member Functions: If the class lacks these members, the compiler uses Argument-Dependent Lookup (ADL) to find non-member
begin(__range)andend(__range).
Object Lifetimes and C++23 Extension
Understanding the compiler expansion is critical for grasping object lifetimes. Prior to C++23, only the object returned by therange_expression itself (__range) had its lifetime extended to the end of the loop. Any other temporaries created within the evaluation of the range_expression were destroyed at the end of the full expression. This frequently caused dangling references. For example, in for (auto c : get_optional_string().value()), the temporary std::optional returned by get_optional_string() would be destroyed before the loop body executed, leaving the hidden __range variable bound to a reference inside a destroyed object.
As of C++23 (P2718R0), the lifetimes of all temporaries materialized during the evaluation of the range_expression are extended to the end of the loop, safely preserving them for the duration of the iteration.
Range Declaration Type Deduction
Therange_declaration dictates how elements are bound during iteration. Because it relies on the dereferenced iterator (*__begin), the choice of type qualifiers directly impacts memory semantics:
std::move_iterator), or elide the operation entirely if the iterator yields a prvalue (due to guaranteed copy elision). x is an independent, mutable object. When used with proxy objects (like std::vector<bool>), this initializes x with the proxy itself, which still correctly reads or mutates the underlying container memory.
x directly to the memory location of the element. Allows in-place mutation of the underlying range elements. Fails to compile if the range yields prvalues or temporary proxy objects.
x to the element as a read-only reference. Prevents copying while enforcing immutability. Extends the lifetime of materialized temporaries if the range yields prvalues.
std::vector<bool> (which would fail to bind to auto&).
Master C++ with Deep Grasping Methodology!Learn More





