Constructors & Destructors
A constructor establishes a class’s invariants when an object comes into existence; a destructor releases its resources when the object dies — the pair that makes raii work.
Why it matters
This pair is the spine of deterministic resource management: a lock acquired in a constructor and released in a destructor cannot leak even if an exception unwinds the stack. It is why C++ needs no finally and no garbage collector — see object-lifetime. Getting initialization order and destructor noexcept right is the difference between a tight RAII type and a double-free.
How it works
Constructors run base classes first, then members in declaration order (not init-list order), then the body. Destructors run the exact reverse.
- Member init list
: a_(x), b_(y)initializes; assigning in the body instead default-constructs then assigns — slower and impossible forconst/reference members. - Special members the compiler may generate: default ctor, copy/move ctor, copy/move assign, destructor — see the-rule-of-0-3-5 and copy-move-constructors.
explicitblocks implicit conversions:explicit Buf(int);stopsBuf b = 5;and accidental conversions in overload resolution.- A destructor must not throw; it is implicitly
noexcept. Throwing during stack unwinding callsstd::terminate. - Delegating ctor:
Foo() : Foo(0) {}reuses another ctor;= default/= deleterequest or forbid a special member.
Example
Declaration order, not list order, drives initialization:
struct W {
int a_;
int b_;
W(int x) : b_(x), a_(b_) {} // a_ runs FIRST (declared first):
}; // reads b_ before it is set -> garbageThe fix is to list members so dependencies are declared earlier; compilers warn with -Wreorder.
Pitfalls
- Calling a
virtualfrom a ctor/dtor dispatches to the current class, not the derived override — the object isn’t fully formed yet. -Wreorderbug: init list reordered relative to declaration silently uses uninitialized members.- Forgetting to free a raw resource in the destructor leaks; prefer smart-pointers-unique-ptr-shared-ptr-weak-ptr so the dtor is
= default. - A throwing destructor during unwinding terminates the program; mark cleanup
noexceptand swallow errors.