A loop repeats a statement while its continuation rule allows another iteration. Correctness depends on the initial state, the condition, the state change, and an invariant that remains true every time control reaches the loop body.
Use a range-based loop when visiting every element, a for loop when initialization and update belong together, a while loop when repetition is driven by an event or sentinel, and do-while only when the body must run before the first test.
Use for when the iteration range is clear. Use while when repetition depends on a changing condition. Use do-while when the body must run at least once. Use range-for when traversing every element.
Nested loops multiply work. Two loops over n items often mean O(n^2). Sometimes that is acceptable, but for large input it may need sorting, hashing, or two-pointer techniques.
Modifying a container while looping over it can invalidate indexes, iterators, or references. Understand the container rules before erasing or inserting inside a loop.
The examples cover counting, range traversal, sentinels, nested work, and mutation boundaries.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> scores = {80, 91, 74, 88};
int total = 0;
for (int score : scores) {
total += score;
}
for (int i = 0; i < (int)scores.size(); i++) {
cout << "Student " << i << ": " << scores[i] << '\n';
}
cout << "Total: " << total << '\n';
}
#include <iostream>
using namespace std;
int main() {
int attempts = 0;
int pin = 0;
while (attempts < 3 && pin != 1234) {
cout << "Enter PIN: ";
cin >> pin;
attempts++;
}
cout << (pin == 1234 ? "Access granted" : "Account locked") << '\n';
}
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> nums = {1, 2, 3, 4, 5, 6};
nums.erase(remove_if(nums.begin(), nums.end(), [](int n) {
return n % 2 == 0;
}), nums.end());
for (int n : nums) cout << n << ' ';
}
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> nums = {1, 2, 3};
for (int i = 0; i < (int)nums.size(); i++) {
for (int j = i + 1; j < (int)nums.size(); j++) {
cout << nums[i] << ',' << nums[j] << '\n';
}
}
}
The usual cause is a boundary mismatch such as <code>i <= size</code> when valid indexes stop at <code>size - 1</code>. For containers, prefer <code>i < values.size()</code> or a range-based loop.
<code>vector::erase</code> invalidates the erased iterator and every iterator after it. Continue with the iterator returned by <code>erase</code> rather than incrementing the old one.
Use <code>auto&</code> when the loop must modify container elements, <code>const auto&</code> to inspect expensive objects without copying, and a value when a deliberate copy is cheap or required. Accidentally using a value while updating only changes the copy, which is why the original container appears unchanged.
Explore 500+ free tutorials across 20+ languages and frameworks.