Tuesday Coding Tip 46 — Attribute initialization

Jakub Neruda
2 min readApr 30, 2024

Tuesday coding tips are short posts about various tidbits mainly from C++, but also from other programming languages I use. You can also follow the #TuesdayCodingTips hashtag on Mastodon and LinkedIn.

When you start learning C++, many sources will tell you to always explicitly initialize member attributes of your classes. But why?

There are two things at play — when a user-defined constructor is invoked, the insides of the class are half initialized/half raw memory. Attributes that are trivial types (int, float) have no default constructor to invoke and thus their values will be unspecified (unless you explicitly initialize them).

#include <print>

struct S {
int i;
S() {}
};

struct S2 {
int i;
};

struct S3 {
int i;

S3() = default;
};

int main() {
std::println("I {}", S().i); // I 32637
// Following two are okay, because the constructor
// is not user-provided, it is compiler-generated.
// Thus, even trivial types are default-initialized.
std::println("I {}", S2().i); // I 0
std::println("I {}", S3().i); // I 0
}

Objects will have their default constructors called, but in the order they were declared in the class definition. If you are not careful, you can invoke a method on an object where the constructor hasn’t been invoked yet.

#include <print>

struct Logger {
Logger() {
std::println("Logger::ctor");
}

int get() const {
std::println("Logger::get");
return 42;
}
};

struct S {
Logger l;
int i;
S() : i(l.get()) {}
};

struct S2 {
int i;
Logger l;
// warning: field 'l' is uninitialized when used here [-Wuninitialized]
S2() : i(l.get()) {}

};

int main() {
S();
// outputs:
// Logger::ctor
// Logger::get

S2();
// outputs:
// Logger::get
// Logger::ctor
}

Explicit initialization can be done in one of three ways — in the attribute declaraction, in the initializer list, or in the constructor body. In all cases, do mind the initialization order of variables.

#include <print>

struct Logger {
Logger(int i) {
std::println("Logger::ctor({})", i);
}
};

struct S {
Logger l;
int i = 42;

// warning: field 'i' is uninitialized when used here [-Wuninitialized]
S() : l(i) {}
};

int main() {
S(); // outputs: Logger::ctor(779647075)
}

--

--

Jakub Neruda

10+ yrs of C++ experience. I care about Clean code, Software architecture and hobby gamedev.