These are the C++-only posts from Simon blogs.
Apropos uniform initialization syntax.
I've used C++ for 16 years now and I still don't know every case of where the language guarantees a zero initialization and when it may leave something uninitialized.
Everybody learns early on that this int is uninitialized:
void foo() {
int a1;
}And that's about as far as "everybody knows" goes, I'd wager.
Only
many people, including me, know that these two are zero-initialized (although I'd still add the explicit
= 0):
int a2; // at global scopevoid bar() {
static int a3;
}The design reason behind this is that these ints live in "static land" instead of going on the stack where the zero initialization would cost runtime: The
BSS section is a memory region that comes preinitialized for free when the operating system loads your executable and has to copy all of the executable code into memory anyway.
But I have no clue of the following, although I see this occasionaly in the day job, usually in C code that somebody renamed to
.cpp later:
void baz() {
int arr1[5] = {}; // Is anything zero? int arr2[5] = {0}; // Are the subsequent four ints also zero?}And do those initializations mean something different in C and in C++? Does it depend on the version of the C standard?
Here are some fun ways to initialize a single int, most of which only arise in theory. This is perfectly legal code that compiles. Are they all zero, are only some zero, are they all possibly uninitialized? I don't know.
void blub() {
int a4{};
int a5 = {};
int a6 = int{};
int a7 = int();
int a8{int()};
int a9 = {int()};
int* p1 = new int;
int* p2 = new int{};
int* p3 = new int();
}The two cases I should look up for definitive clarification are
a4{}; and
a5 = {};. The others might also be enlightening eventually, but expressions such as
int() come up rarely enough that you can deem those esoteric.
And it doesn't end with ints where you have a chance at initializing them explicitly with zero. Occasionally useful in real life: You have
std::vector<int> and you want to enlarge it by calling
resize(). Does it zero-initialize the new values?
I have dark memories of possible nonequivalence of the following. It might be a false memory from early learner days in 2006, but I've never clarified it. Assume
X is a class with a custom default constructor, and no other constructors (in particular,
X doesn't define a constructor that takes a
std::initializer_list). Do all of these run the default constructor? Quick reality check with
g++ --std=c++17 tells me: Yes, all of them run the default constructor. But does the language really guarantee it, ever since C++98? I assume so, then...
void blip() {
X x1;
X x2{};
X x3 = {};
X x4 = X();
X x5 = X{};
X* x6 = new X;
X* x7 = new X();
}I should really read the standard directly more.
-- Simon