Modern C++ Class Design: Constructors, Rule of Five, Member Init & Special Members (C++23)

Modern C++ Class Design: Constructors, Rule of Five, Member Init & Special Members (C++23)
Table of Contents
- The Complete C++ Object Lifecycle
- Member Initializer Lists: Order Matters
- Constructor Types: A Complete Reference
- The explicit Keyword: Preventing Silent Conversions
- =default and =delete: Explicit Compiler Control
- The Rule of Zero: Prefer Composition
- The Rule of Five: Raw Resource Management
- Writing a Complete Buffer Class
- Destructor Order and Virtual Destructors
- C++20/23 Improvements: Designated Initializers & Aggregates
- Frequently Asked Questions
- Key Takeaway
The Complete C++ Object Lifecycle
Member Initializer Lists: Order Matters
Never assign in the constructor body when you can initialize in the member initializer list. Initialization is always faster (no default-construct + assign), and for const members and references it's mandatory:
[!IMPORTANT] Members are always initialized in declaration order (the order they appear in the class body), regardless of the order in the initializer list. A mismatch causes subtle bugs — most compilers warn about this with
-Wreorder.
Constructor Types: A Complete Reference
The explicit Keyword: Preventing Silent Conversions
Without explicit, single-argument constructors enable implicit type conversion — a common source of bugs:
Rule: Mark all single-argument constructors explicit unless you specifically intend implicit conversion (e.g., std::string from const char* is deliberately implicit).
=default and =delete: Explicit Compiler Control
= default tells the compiler to generate the optimal default implementation. = delete removes the operation entirely, turning misuse into a compile error:
The Rule of Zero: Prefer Composition
If your class only contains RAII members (smart pointers, containers, string), the compiler generates correct copy/move/destroy automatically — don't write any special member functions:
The Rule of Five: Raw Resource Management
When you must own a raw resource (legacy C API, custom allocator, hardware register), implement all five:
Destructor Order and Virtual Destructors
C++ destroys objects in the reverse order of construction:
C++20/23 Improvements: Designated Initializers
Frequently Asked Questions
When must I write my own destructor?
Only when your class directly owns a raw resource that isn't wrapped in RAII (raw new/delete, C API handles like FILE*, OS resources like file descriptors). If all your members are RAII types, let the compiler generate the destructor via the Rule of Zero.
Why must move constructors be noexcept?
std::vector::push_back may reallocate. During reallocation, it must move all existing elements to the new memory. If a move constructor can throw, the vector cannot safely use it (the move might partially succeed, leaving both old and new storage in inconsistent states). With noexcept, the vector uses moves. Without it, it falls back to copies — potentially 10-100× slower for large element types.
What is the difference between initialization and assignment?
Initialization creates a new object (int x = 5 or int x(5) or int x{5}). Assignment modifies an existing object (x = 5). In class terms: MyClass a = b calls the copy constructor (initialization). a = b where a already exists calls copy assignment operator. The member initializer list performs initialization — always prefer it over body assignment.
Key Takeaway
C++ class design is deterministic lifecycle management. Every resource acquisition must have a corresponding release path that runs even when exceptions occur. The Rule of Zero says: compose from RAII types and let the compiler handle everything. The Rule of Five says: when you must touch raw resources, implement all five special members explicitly, correctly, and with noexcept on move operations. There is no middle ground — a class that defines the destructor but not the copy/move operations silently uses the wrong behavior.
Read next: OOP vs Composition: Interfaces & Polymorphism →
Part of the C++ Mastery Course — 30 modules from modern C++ basics to expert systems engineering.
