Quiz 10 — Answers¶
Q1 — B, a shallow copy. The default copy constructor copies each member, and for an
int* that means copying the address. Both objects then point at one buffer — usually a
double free at destruction.
Q2 — True (with a caveat). Declaring a destructor does not delete the copy constructor; the compiler still generates one (deprecated, but present). The danger is that it is a shallow copy. Declaring a destructor does suppress the implicit move operations, which is a different consequence.
Q3 — A, B, C. The Rule of Three says: if you write any one of them you likely need all three (A); it applies to classes that own a resource (B); the three are the destructor, copy constructor and copy assignment (C). It does not require a move constructor (D) — that is the Rule of Five.
Q4 —
The deep copy constructor allocates a new buffer and copies the values, so b[0] = 7 does
not touch a. Without the copy constructor, both would share one buffer and print 7 7
before crashing on the double free.
Q5 —
The move constructor takes the id (10) and sets the source's id to -1; the destructor
stays silent for the moved-from object. Only b, which owns the real resource, prints
close. A moved-from object is valid but unspecified — safe to destroy or assign to,
not to rely on.
Q6 — On x = x, line (1) frees x's buffer and line (2) then reads from the
now-freed storage — undefined behaviour (and the destructor frees it again). Fix with a
self-assignment guard:
or use the copy-and-swap idiom, which needs no guard.
Q7 — It needs to write none of them. Members that manage their own resources
(std::string, std::vector) already implement the Rule of Five correctly, so the
compiler-generated destructor, copy and move are all correct. This is the Rule of Zero.
Q8 — A moved-from object is in a valid but unspecified state: its invariants hold
and it can be destroyed or assigned to, but its value is not defined. For unique_ptr and
many hand-written types it is empty/null, but you must not rely on any particular value.
Q9 — copy prints twice, then size 2.
reserve(2) prevents reallocation, so the only copies come from push_back copying its
temporary into the vector. Tag declares a destructor and a copy constructor and no move
constructor, so push_back copies rather than moves. Two pushes, two copies.
Q10 — Because the grade book holds a std::vector<double> (or similar), it can write
none of the five — the Rule of Zero applies. If it must own a raw array, it needs the
destructor, copy constructor and copy assignment (Rule of Three), and optionally the move
constructor and move assignment (Rule of Five) for efficiency; the move leaves the source
empty and destructible. Writing the vector version is preferable because there is nothing to
get wrong.
Marking. One point per question (Q3 all-or-nothing). Then read Marking Yourself.