Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does C++ default-initialization preserve prior zero-initialization?

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

like image 510
user1998586 Avatar asked Oct 31 '15 20:10

user1998586


People also ask

Does default constructor zero initialize?

Implicitly defined (by the compiler) default constructor of a class does not initialize members of built-in types.

Does C++ initialize variables to zero?

Unlike some programming languages, C/C++ does not initialize most variables to a given value (such as zero) automatically. Thus when a variable is assigned a memory location by the compiler, the default value of that variable is whatever (garbage) value happens to already be in that memory location!

Is ints 0 by default C++?

Well, int's are value types in both c++ and C#, they use X bytes of ram, and all 0 bits, they are 0. So whether you initialize them or not, in memory they are still 0. Whether they are zero initialized or not depends on their storage type (static or automatic) and on how they are initialized.

Is initialized to zero when the first object is created?

A static member is shared by all objects of the class. All static data is initialized to zero when the first object is created, if no other initialization is present.


1 Answers

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.

like image 62
Shafik Yaghmour Avatar answered Nov 09 '22 23:11

Shafik Yaghmour