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?
Practice Playground
Time to try out what you just learned! Play with the example code below, experiment by making changes and running the code to deepen your understanding.
Output:
Error:
Lesson Progress
- Fix This Code
- Quick Quiz
- Practice Playground - run once