Object Initialization
Without user-defined constructor
Section titled “Without user-defined constructor”Without in-class member initializers
Section titled “Without in-class member initializers”struct Widget{ int i; // Uninitialized by default std::string s; // default constructed by default int* pi; // Uninitialized by default};
int main() { Widget w; // Default initialization of an aggregate w.i; // Uninitialized w.s; // Default constructed: "" w.pi; // Uninitialized
Widget w2{}; // Value initialization when user-provided constructor is absent: // zero-initialize scalars + default-initialize class members. w2.i; // 0 w2.s; // Default constructed: "" w2.pi; // nullptr}Guideline: Prefer brace {} initialization when no in-class member initializers are present. It guarantees scalars and pointers are zero-initialized and class members are default-constructed.
With in-class member initializers
Section titled “With in-class member initializers”struct Widget{ int i{}; // value-initialized: 0 std::string s{}; // default constructed: "" int* pi{}; // value-initialized: 0};
int main() { Widget w; // Default initialization of an aggregate // members get their in-class initializers w.i; // 0 w.s; // "" w.pi; // nullptr
Widget w2{}; // Same}Guideline: Prefer in-class member initializers to give safe defaults. This eliminates uninitialized state even when using plain T obj;
With empty default constructor
Section titled “With empty default constructor”If there is an explicitly defined empty default constructor, it leaves fundamental type members uninitialized, while class-type members are still default-constructed.
struct Widget{ Widget() {} int i; // Uninitialized std::string s; // Default constructor (empty string), because class type int* pi; // Uninitialized};
Widget w; // Uninitialized w.i and w.piWidget w2{}; // Uninitialized w2.i and w2.piGuideline: Avoid writing an empty default constructor. But also C.45: Don’t define a default constructor that only initializes data members; use default member initializers instead. A default constructor should do more than just initialize data members with constants.
Preference of initialization styles
Section titled “Preference of initialization styles”Numbered in order of preference, 1 being preferred most, 3 being least preferable:
struct Widget{ std::string s = "hello world"; // 1. In-class member initializer (preferred) // std::string s{"hello world"}; // 1. Equivalent std::string s2;
Widget() : s2{"hello world"} // 2. Member initializer list { // s2 = "hello world"; // 3. Least preferred: default-construct + assign (performance impact) }};Prefer in-class initialization over constructor initialization, because it can eliminate the need for a trivial constructor (C.45).
Member Initialization Order
Section titled “Member Initialization Order”struct Widget { std::string s = "first"; // In-class initializer
Widget() : s("second") { // Member initializer list overrides in-class initializer s = "last"; // Assignment in constructor body happens last }};