5.2.6 · D5C++ Programming
Question bank — Constructors — default, parameterized, copy, delegating
Prerequisite ideas leaned on here: Member Initializer Lists, Destructors and RAII, Copy Assignment Operator, Rule of Three Five Zero, explicit keyword and implicit conversions, and Move Semantics — move constructor.
True or false — justify
If a class declares only a parameterized constructor, ClassName obj; still compiles.
False — declaring any constructor stops the compiler from synthesizing the default one, so the no-argument form is not available until you add
ClassName() = default;.A constructor may have a return type as long as it is void.
False — a constructor has no return type at all, not even
void; writing one turns it into an ordinary member function that happens to share the class name.The copy constructor and the copy assignment operator are the same function.
False — the copy constructor builds a brand-new object from an existing one, while copy assignment (Copy Assignment Operator) overwrites an already-constructed object; different signatures, different jobs.
A default constructor is always one that takes zero arguments literally.
False — a constructor counts as "default" if it can be called with no arguments, so
ClassName(int x = 0) (all-defaulted parameters) also qualifies.Marking a copy constructor explicit has no observable effect.
False —
explicit blocks the copy-initialization form T b = a; while still allowing direct-initialization T b(a);, so it changes which syntaxes compile.The compiler-generated copy constructor is always unsafe for classes that own heap memory.
True — the synthesized version does a member-wise shallow copy, so two objects end up owning the same pointer and both destructors
delete[] it, giving a double free.Delegating to another constructor lets you also initialize a member in the same list.
False — the delegation call must be the only entry in the initializer list; the target constructor is responsible for all member init before the delegating body runs.
A const object can be passed to a copy constructor.
True — that is exactly why the parameter is
const ClassName&; without const you could not copy from const sources or temporaries.Spot the error
class C { C(C other){} }; — what breaks?
Taking the copy source by value means copying the argument would itself invoke the copy constructor → infinite recursion; the parameter must be
const C&.Point() : Point(0,0), x(1) {} — why is this rejected?
A delegating constructor's list may contain only the delegation call; adding
x(1) mixes delegation with direct member init, which is illegal.A() : A(0) {} together with A(int) : A() {} — what's wrong?
This forms a delegation cycle
A() → A(int) → A() with no real target constructor, giving undefined behaviour / an endless loop at construction.class T { int b, a; T(int v) : a(v), b(a) {} };Why might b hold garbage?
Members initialize in declaration order (
b before a), not list order, so b(a) reads a while a is still uninitialized.Meter m = 5; compiles even though 5 is an int — why is that a hidden trap?
A non-
explicit single-argument constructor allows an implicit conversion int → Meter, silently constructing an object where the reader expected plain assignment (see explicit keyword and implicit conversions).A class writes a destructor that frees a pointer but keeps the default copy constructor — what's the latent bug?
The Rule of Three (Rule of Three Five Zero) is broken: copies share the pointer, so the second destructor double-frees; you need a matching deep-copy constructor and copy assignment.
Point(int a, int b) { x = a; y = b; } for const int x, y; — why won't it compile?
const members can only be initialized, never assigned; inside the body {} you are assigning after default-init, so they must go in the initializer list instead.Why questions
Why does the initializer list beat assigning inside the constructor body for class-type members?
The list direct-initializes in one step, whereas body assignment first default-constructs the member then overwrites it — two operations, and impossible for
const/reference members.Why can't a normal constructor be virtual?
Virtual dispatch needs a fully-built object with a valid vtable pointer, but the constructor is what sets that up, so there is nothing to dispatch through yet.
Why does returning an object by value potentially fire the copy constructor?
A by-value return conceptually copies the local into the caller's slot; the copy constructor is the recipe for that copy (though copy-elision often removes it in practice).
Why is a deep copy needed when a class holds int* data?
Each object must own an independent buffer, so allocating fresh memory with
new and copying the elements prevents two objects from sharing and double-freeing the same block.Why keep single-argument constructors explicit by default as a habit?
It forbids surprising silent conversions, forcing callers to write the construction intentionally (
Meter m(5)) rather than have 5 morph into a Meter behind their back.Why does defining a move constructor also suppress the implicit copy constructor?
Under the Rule of Five (Move Semantics — move constructor), declaring any of the special resource-managing functions signals custom ownership, so the compiler stops guessing and withholds the others.
Edge cases
What happens for ClassName arr[10]; if the class has no accessible default constructor?
It fails to compile — array elements are each default-constructed, so a usable no-argument constructor must exist and be reachable.
Is a shallow copy ever actually correct?
Yes — for classes whose members are all value types (like
Point{int x, int y}), member-wise copy duplicates everything cleanly, so the compiler-generated copy constructor is exactly right.What is the construction order for a Derived object with member objects?
Base classes first (declaration order), then member objects in class declaration order, and only then does the constructor body run.
Can a delegating constructor run its own body after delegating?
Yes — the target constructor completes fully first, then control returns and the delegating constructor's body
{...} executes, letting you add extra steps after shared setup.What does Point() = default; do that plain Point() {} does not?
= default asks the compiler to synthesize the standard member-wise default, keeping the type trivially default-constructible where possible, instead of you supplying a user-provided (non-trivial) empty body.If copy elision removes the copy on a by-value return, does the copy constructor still need to exist?
Yes — even when the copy is elided, the copy constructor must be accessible and not deleted, because the language checks it as if the copy could happen.
Recall One-line self test
The moment you write ~ClassName(), which two other functions should immediately come to mind?
Which order wins for member init — the list order or the declaration order?
Copy this next to your compiler warnings; every trap here maps to a real -Wreorder, -Wself-move, or double-free you'll otherwise meet at runtime.