问题
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)?
回答1:
Defect report 1787 lead to the change documented in N3914 being applied to the draft standard for C++14. Which change [dcl.init] paragraph 12 from:
If no initializer is specified for an object, the object is default-initialized; if no initialization is performed, an object with automatic or dynamic storage duration has indeterminate value. [ Note: Objects with static or thread storage duration are zero-initialized, see 3.6.2. — end note ]
to:
If no initializer is specified for an object, the object is default-initialized. When storage for an object with automatic or dynamic storage duration is obtained, the object has an indeterminate value, and if no initialization is performed for the object, that object retains an indeterminate value until that value is replaced (5.17 [expr.ass]). [Note: Objects with static or thread storage duration are zero-initialized, see 3.6.2 [basic.start.init]. —end note] If an indeterminate value is produced by an evaluation, the behavior is undefined except in the following cases:
[...]
This make it clear the indeterminate value situation only occurs for objects of automatic or dynamic storage duration. Since this was applied via a defect report it probably also applies to C++11 since the defect report occured before C++14 was accepted but it could apply further back as well. The rules for how far back a defect are supposed to apply were never clear to me.
Since placement new was brought up in the comments, the same change also modified section [expr.new], making the indeterminate value portion a comment:
If the new-initializer is omitted, the object is default-initialized (8.5 [dcl.init]); if. [Note: If no initialization is performed, the object has an indeterminate value. —end note]
The beginning of the section says:
[...]Entities created by a new-expression have dynamic storage duration (3.7.4).[...]
Which seem sufficient to apply the changes in section [dcl.init].
This change was also interesting since prior to this change the term indeterminate value was not defined in the C++ standard.
来源:https://stackoverflow.com/questions/33456141/does-c-default-initialization-preserve-prior-zero-initialization