Skip to content

Object Initialization

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.

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;

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.pi
Widget w2{}; // Uninitialized w2.i and w2.pi

Guideline: 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.

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).

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
}
};