Step 4 of 6
Review: modifying while iterating
Another classic: changing a container while looping over it.
- erasing index
ishifts the next element into positioni, and theni++skips it push_backduring a range-for can reallocate, invalidating the loop's hidden iterators- a reference taken before a
push_backcan dangle afterwards
Spotting the skip
Run the erase loop by hand on an input with two matches next to each other, like {a, X, X, b} where X should be removed:
i = 1: erase X -> {a, X, b} then i++ -> i = 2
i = 2: b the second X, now at index 1, was never checked
The safe patterns: only increment when nothing was erased, use std::erase_if, or build a new vector of the items you keep.
#include <iostream>
#include <string>
#include <vector>
int main() {
std::vector<std::string> queue = {"ok", "spam", "spam", "ok", "spam"};
for (std::size_t i = 0; i < queue.size(); ) {
if (queue[i] == "spam") queue.erase(queue.begin() + i); // don't advance
else i++; // advance only when keeping
}
for (const auto& m : queue) std::cout << m << " ";
std::cout << "(" << queue.size() << ")\n";
std::vector<int> v = {1, 2, 3};
int first = v.front(); // a copy, not a reference: safe after growth
for (int i = 0; i < 100; i++) v.push_back(i);
std::cout << first << "\n";
}
ok ok (2)
1
Adding while looping
A range-for over roster that calls roster.push_back is undefined behavior: the loop's hidden iterators point into the old buffer after a reallocation. If you need to add a number of items, compute the count first, then add them in a separate plain loop that doesn't iterate over the container.
The dangling reference
const std::string& captain = roster.front(); refers to an element inside the vector. After push_back reallocates, it refers to freed memory. Copy the value (std::string captain = ...) when you need it to survive changes to the container.
Your turn: this pull request enforces bans and fills the roster back up with substitutes. Fix it so that every banned player is removed (including when two are adjacent), one substitute is added per removed player, and captain returns the right name. There are three bugs.
Previous: Review: leaks on the error path Next: Review: integer math