We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Values, Types, Initialisation step 4 of 4
auto copies, and does not say so
for (auto item : items) {
item.count += 1;
}
This compiles, runs, and does nothing. Not “does something subtly wrong” —
nothing at all. The loop body increments a field on a copy that is destroyed
at the end of each iteration, and items is untouched when it finishes.
What auto actually does
auto deduces the type of the initialiser and then strips references and
top-level const. So:
const std::string& ref = get_name();
auto a = ref; // std::string — a copy, and mutable
auto& b = ref; // const std::string& — bound, cannot mutate
const auto& c = ref; // const std::string& — bound, says so
auto&& d = ref; // const std::string& — binds to anything
Only a copies. The other three are the same object under a different name.
This is not a quirk; it is the same rule template argument deduction uses,
and auto was defined to match it deliberately. But the consequence is that
auto alone means “a fresh independent value”, which is very often not
what was intended.
Two failure modes, one cause
-
Mutation goes nowhere. The loop above. Silent, and the test that catches it is the one that checks the container afterwards.
-
A copy you did not want. For a
std::stringor astd::vectorthat is an allocation per iteration.performance-for-range-copyexists because this is common enough to have a lint of its own.
The four forms, and when each is right
| Form | Use when |
|---|---|
const auto& |
Reading. The default for a range-for. |
auto& |
Mutating the element in place. |
auto |
You genuinely want an independent copy, or the type is cheap — int, a pointer, an iterator. |
auto&& |
Generic code, or iterating something that yields temporaries (std::vector<bool>, views, zip). |
If you take one habit from this problem: write const auto& in a range-for
by default, and change it only when you mean to.
Your task
struct Word {
std::string text;
int count;
};
void tally(std::vector<Word>& words, const std::string& target);
Increment count on every Word whose text equals target, in place.
The starter is written the way it usually gets written first. It compiles cleanly, and every test fails.
Stuck?
C++ reference solution
Sign in to attempt this problem and reveal the reference solution.