Range-Based For Loops
Simplify iteration with C++11's range-based for loops for cleaner, safer code
Learn how to iterate over containers safely and elegantly using C++11's range-based for loops.
A Simple Example
#include <iostream>
#include <vector>
#include <string>
int main() {
std::vector<int> numbers{10, 20, 30, 40, 50};
// Old style - error prone
for (size_t i{0}; i < numbers.size(); ++i) {
std::cout << numbers[i] << " ";
}
std::cout << "\n";
// Range-based - clean and safe
for (int num : numbers) {
std::cout << num << " ";
}
std::cout << "\n";
// With auto for type deduction
for (auto num : numbers) {
std::cout << num << " ";
}
std::cout << "\n";
// Modifying elements - use reference
for (auto& num : numbers) {
num *= 2; // Double each number
}
// Read-only - use const reference (avoids copies)
for (const auto& num : numbers) {
std::cout << num << " ";
}
std::cout << "\n";
return 0;
}
Breaking It Down
Basic Range-Based For Syntax
-
Syntax:
for (type variable : container) { } - What it does: Iterates through each element in the container automatically
- No indices needed: Eliminates off-by-one errors and index management
- Remember: Much cleaner than traditional for loops with manual indexing
Using auto for Type Deduction
-
Syntax:
for (auto item : container)- compiler deduces the type - Benefit: Less typing, works with complex types, adapts to container changes
- Creates copies: Each iteration copies the element unless you use a reference
- Remember: auto makes your code more flexible and maintainable
Modifying Elements with References
-
Syntax:
for (auto& item : container)- note the ampersand - What it does: Gives you a reference to the original element, not a copy
- Use when: You need to modify elements in place
- Remember: Without &, you modify a copy that gets discarded
Read-Only Access with const auto&
-
Syntax:
for (const auto& item : container) - Benefits: No copying (fast) + prevents accidental modification (safe)
- Best for: Large objects like strings or custom types
- Remember: This is the recommended default for read-only iteration
Why This Matters
- Traditional for loops with indices are error-prone: off-by-one errors, wrong comparison operators, forgetting to increment.
- Range-based for loops eliminate these bugs by iterating directly over elements.
- They're safer, clearer, and work with any container - arrays, vectors, maps, or even your custom types.
Critical Insight
Range-based for loops use iterators behind the scenes. When you write for (auto x : container), the compiler generates code equivalent to for (auto it = container.begin(); it != container.end(); ++it).
This means range-based loops work with ANY type that has begin() and end() methods - including your custom containers! The compiler does all the iterator management for you.
Best Practices
Default to const auto& for read-only iteration: Avoids unnecessary copies and prevents accidental modification. This is the safest and most efficient choice.
Use auto& when modifying elements: Only use a non-const reference when you actually need to change the elements in place.
Avoid modifying container size during iteration: Don't add or remove elements while iterating - it invalidates iterators and causes undefined behavior.
Use traditional loops when you need indices: If you need the position or want to skip elements, a traditional indexed loop might be clearer.
Common Mistakes
Forgetting the reference: for (auto x : vec) copies each element. For large objects, this is slow. Use const auto& instead.
Modifying container while iterating: Don't add/remove elements during range-based iteration - it invalidates iterators and causes crashes.
Using range-based loops for parallel iteration: If you need to iterate over multiple containers together, use traditional indexed loops.
Expecting modification without &: Without a reference, changes to the loop variable don't affect the original container.
Debug Challenge
This code tries to double all numbers in a vector but it doesn't work. Click the highlighted line to fix it:
Quick Quiz
- How do you modify elements in a range-based for loop?
- What's the benefit of
const auto&overauto?
- Can you use range-based for with C-style arrays?
Step Through the Code
Walk through the code step by step. Watch how variables change and see the program output at each line.
Variables
Output
Stack / Heap
Output:
Error:
Lesson Progress
- Fix This Code
- Quick Quiz
- Practice Playground - run once