We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Copy, Move, and the Rule of Zero step 3 of 5
The line that does nothing, twice a second
Every class has five special member functions. You get them whether or not you write them:
~T(); // destructor
T(const T&); // copy constructor
T& operator=(const T&); // copy assignment
T(T&&) noexcept; // move constructor
T& operator=(T&&) noexcept; // move assignment
The compiler generates each one memberwise: destroy each member, copy each
member, move each member. For a class whose members are std::vector,
std::string, std::unique_ptr — types that already manage themselves —
the generated versions are exactly right, and better than what you would
write, because they cannot drift out of sync with the member list when
someone adds a field.
The rule of zero: if your class does not directly own a raw resource, declare none of the five.
The trap, which is the reason this problem exists
These five are not independent. Declaring one changes what you get for the others, and the rule that bites is:
Declaring a destructor — or a copy operation — suppresses the implicit move constructor and move assignment operator.
Suppressed, not deleted. The class still compiles, still copies, and
std::move on it silently selects the copy constructor, exactly as in the
previous problem. Your type has quietly become expensive, and nothing about
the destructor you wrote suggests it.
And = default does not save you. This:
~Session() = default;
is a user-declared destructor. It generates the same code the compiler would have, and it suppresses moves just as thoroughly as a hand-written one. The fix is not to default the line. The fix is to delete the line.
The rule of five, in one sentence
If you genuinely must write one of the five — because your class owns something raw — write all five, because the compiler has stopped helping. That is the next problem. This one is about the far more common case, where the right answer is to write none.
Your task
collect is given and already correct: it moves every session into a new
vector. Do not change it.
std::vector<Session> collect(std::vector<Session>& sessions);
Session holds a Counted member, which counts the copies and moves made of
it, and the harness reports both. Right now every session is copied, and
one line in Session is the reason.
Find it, and get copies to zero without changing collect or Counted.
Stuck?
C++ reference solution
Sign in to attempt this problem and reveal the reference solution.