> ## Documentation Index
> Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# C++ Range-Based For Loop

A range-based `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

```cpp theme={"dark"}
for ( init-statement_opt range_declaration : range_expression ) {
    loop_statement
}
```

* **`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, an `init-statement` inherently 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 utilizing `auto` combined with reference (`&`, `&&`) and `const` qualifiers.
* **`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 exposes `begin()` and `end()` 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-based `for` loop into an equivalent traditional `for` loop.

A standard range-based `for` loop translates to the following underlying structure:

```cpp theme={"dark"}
{
    init-statement_opt // If provided (C++20)
    auto && __range = range_expression;
    auto __begin = begin_expr;
    auto __end = end_expr;
    for ( ; __begin != __end; ++__begin ) {
        range_declaration = *__begin;
        loop_statement
    }
}
```

*Note: As of C++17, the types of `__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`:

1. **Built-in Arrays**: If `__range` is an array of known bound, it resolves to pointers to the first element and one past the last element (`__range` and `__range + bound`).
2. **Member Functions**: If `__range` is a class type possessing `.begin()` and `.end()` member functions, it resolves to `__range.begin()` and `__range.end()`.
3. **Non-Member Functions**: If the class lacks these members, the compiler uses Argument-Dependent Lookup (ADL) to find non-member `begin(__range)` and `end(__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 the `range_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

The `range_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:

```cpp theme={"dark"}
// 1. By Value
for (auto x : range) 
```

Performs copy-initialization for each element. Depending on the iterator's reference type, this may invoke a copy constructor, a move constructor (e.g., if iterating over a range with `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.

```cpp theme={"dark"}
// 2. Lvalue Reference
for (auto& x : range) 
```

Binds `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.

```cpp theme={"dark"}
// 3. Const Lvalue Reference
for (const auto& x : range) 
```

Binds `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.

```cpp theme={"dark"}
// 4. Forwarding Reference (Universal Reference)
for (auto&& x : range) 
```

Binds to both lvalues and rvalues. This is essential in generic programming where the exact range type is unknown. It ensures that standard container elements are bound by reference (avoiding copies), while also successfully binding to temporary proxy objects returned by containers like `std::vector<bool>` (which would fail to bind to `auto&`).

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor C++ Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
