Range-based For Loop (foreach)
Modern Iteration
Introduced in C++11, the range-based for
loop automatically iterates through all elements in a range without explicit counter management.
Works with raw arrays, std::array
, STL containers, initializer lists, and user-defined types that are range-like (i.e., have begin
/end
member functions or free begin
/end
found by ADL).
Basic Usage
Example
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
vector<string> colors = {"Red", "Green", "Blue"};
for (const auto& color : colors) {
cout << color << '\n';
}
return 0;
}
Output
Red Green Blue
Modification Example
Example
#include <vector>
using namespace std;
int main() {
vector<int> numbers = {1, 2, 3};
for (auto& num : numbers) {
num *= 2; // Double each value
}
}
ℹ️ Note: Use <code>auto&</code> when you need to modify elements; use <code>auto</code> (by value) only when a copy is intended.
Maps & Structured Bindings (C++17)
When iterating key–value containers, structured bindings make code clearer.
Example
#include <map>
#include <string>
#include <iostream>
using namespace std;
int main() {
map<string, int> freq{{"red",1},{"green",2}};
for (auto& [key, val] : freq) {
cout << key << ": " << val << '\n';
++val; // modify value
}
}
Output
red: 1 green: 2
Initializer Lists & Arrays
You can iterate braced lists and raw arrays directly.
Example
#include <iostream>
using namespace std;
int main() {
for (int x : {2, 4, 6, 8}) cout << x << ' ';
cout << '\n';
int arr[] = {10, 20, 30};
for (int& x : arr) x += 1; // mutate elements
}
Output
2 4 6 8
C++20: Init-statement in Range-for
Since C++20, you can add an init-statement before the range declaration.
Example
#include <vector>
#include <iostream>
int main() {
for (std::vector v{1,2,3,4}; auto& x : v) {
x *= 3;
}
}
Supported Containers
- Raw (C-style) arrays and std::array
- STL containers (vector, string, list, deque, set, map, unordered_*)
- Initializer lists (e.g., {1,2,3})
- User-defined types with begin()/end() or free begin/end (ADL)
- C++20 ranges/views that expose begin/end
Pitfalls & Tips
- Iteration by value (
auto x
) copies each element; preferconst auto&
for read-only,auto&
for mutation. - Modifying the container (insert/erase) during iteration can invalidate references/iterators for some containers (e.g., vector, string).
- If you need the index, use a traditional index-based loop or maintain a separate counter.
- Order of iteration depends on the container (e.g.,
map
is ordered by key;unordered_map
has no defined order). - With proxy-reference containers like
std::vector<bool>
, useauto&
to actually modify elements.