We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Copy, Move, and the Rule of Zero step 1 of 5
The copy you did not write
In most languages, passing an object around passes a reference to it. In C++ it copies the object — the whole thing, every element, every allocation — and the syntax for that is nothing at all.
for (Payload p : items) { ... } // copies every element
std::vector<int> d = p.data; // copies the vector
void handle(std::string name); // copies the caller's string
None of those lines contain a word that suggests expense. That is the whole
problem: C++ makes the expensive thing invisible and the cheap thing —
const& — six characters longer.
What a copy actually does
Copying a std::vector<int> of a million elements allocates four megabytes
and memcpys into it. Copying a struct that contains three such vectors does
it three times. In a loop over ten thousand items, that is a program that
looks like it is doing arithmetic and is in fact doing allocation.
This is not a micro-optimisation. It is the single most common reason C++ code is slower than the C it replaced, and it is nearly always accidental.
The two lines that cause most of it
1. The range-for that copies.
for (Payload p : items) // copy per element
for (const Payload& p : items) // no copies at all
for (Payload& p : items) // no copies, and you may modify
The & is the entire difference. Write const auto& by default; drop the
const when you need to modify; drop the & only for genuinely cheap types
like int, where a reference costs more than the copy it saves.
2. The named copy of something you only read.
std::vector<int> d = p.data; // copies
const std::vector<int>& d = p.data; // names it, copies nothing
A reference is a name for an existing object. If all you do is read through the name, that is all you needed.
clang-tidy knows
Both of these are checks in the performance-* group that the gate enables:
performance-for-range-copy and performance-unnecessary-copy-initialization.
You will meet them here on purpose, so that when they fire on your own code
later you read them as arithmetic rather than as nagging.
Your task
std::vector<int> heads(const std::vector<Payload>& items);
Return the first element of each non-empty payload, in order. Empty payloads contribute nothing.
The starter is correct and does it with a copy per item. Payload counts its
own copies, and the harness reports that count alongside your answer — so a
correct-but-copying solution fails, which is the judgement a reviewer would
make and a normal test suite would not.
Get the count to zero.
Stuck?
C++ reference solution
Sign in to attempt this problem and reveal the reference solution.