If a C++ constructor for an object with static-storage duration does not initialize a member, is that required to preserve the prior zero-initialization, or does it leave the member with an indeterminate value?
My reading of the C++ spec is that it contradicts itself.
Example:
#include <iostream>
struct Foo { Foo(); int x; } object;
Foo::Foo() { }
int main() { std::cout << object.x << std::endl; }
The Foo() constructor does not explicitly initialize the member object.x, so according to the note in 12.6.2 paragraph 8:
the member has indeterminate value.
But working through the details of the various initializations, this appears to be incorrect. The member object.x is zero-initialized as it has static-storage-duration, and then I can't see anything that changes that.
Regarding the constructor, the text in 12.6.2 that applies is:
the entity is default-initialized.
In 8.5 paragraph 7, the relevant case of default initialization is:
... no initialization is performed
which I read to mean that the previous zero-initialization is not changed by the default-initialization.
Am I missing some other text which resets all members to "indeterminate value" at the start of the constructor call?
I found various other questions on stackoverflow regarding zero-initialization and default-initialization, but I couldn't see any that analyzed what happens when default-initialization follows some early initialization of the same entity.
In this case there is probably no practical effect. But in a more complex constructor, with some members initialized and others not, does the compiler have to track exactly which bytes/bits are initialized?, or can it just initialize the whole object (e.g., simplifying the constructor to a memset() call)?
Foo
is an object with non-trivial initialization, which means its lifetime only has started once its constructor completed. I am not sure about the values of its members, then. Before the constructor has started execution, you may not even access them (by normative rules), so I have a hard time that they have value values (zero) stored by that time.. not to mention the existence of an object in the first place. – BaloneyS *p = malloc(sizeof*p); p->a = 1; new (p) S; /* p now refers to a different, new, object */ int x = p->a;
but this is not valid:S *p = malloc(sizeof*p); int *pa = &p->a; *p = 1; new (p) S; /* p now refers to a different, but pa is dead and not reseated */ int x = *pa; /* UB */
. But remember: I am not an expert on this, and all I say could be all-wrong! This isn't super-clear in the spec... – Baloney