4

When will a fundamental C++ type, such as int or float, have an unknown initial value?

How does the type of memory allocation factor in, if at all? What about the declaration? What if it's a member of a class/struct/union? Is C++11 different from C++03 or C++98?

I have my suspicions, but no idea if my knowledge is complete (or correct, for that matter)

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
  • Well, it depends on the type of initialization. Value initialization will zero them. You can then see when value initialization is used, such as `int i{};`. – chris Feb 08 '13 at 22:13
  • An uninitialized variable will have an unknown initial value, except if it is static or global (in which case it is initialized to all bits 0). – jxh Feb 08 '13 at 22:17
  • *implicit* is not a term that can be applied to types (at least in the standard). You might want to use *fundamental* types or *POD* (plain old data) which include both *fundamental* types and some user defined types composed only of *fundamental* types in a limited set of ways (these share most of the properties of the *fundamental* types). I also provided a list of cases in an answer to your previous question. – David Rodríguez - dribeas Feb 08 '13 at 22:23
  • Related to [Has C++ standard changed with respect to the use of indeterminate values and undefined behavior in C++14?](http://stackoverflow.com/q/23415661/1708801) in C++14 they clarified a lot about indeterminate values. – Shafik Yaghmour Dec 24 '15 at 04:21

2 Answers2

7

Any POD data (including all fundamental types) will have an unknown value when both:

  • it doesn't have static memory allocation (it's instead created on the stack or with new)
  • it isn't initialized, including empty initialization and/or constructor initialization lists

Global/static variables, of all types, are set to zero as part of the startup process before main is called. Constructors are called for types that have constructors before main 1.

Anything not initialized in the constructor is also unknown.

Edit: to clarify, std::string is a good example of "constructor not initializing everything" - if you have a local std::string str;, then str will have a defined "empty string" content, but the content of the actual buffer, or indeed what the buffer points at may not be set to anything meaningful at all - as the implementation may determine based on the length [or some other way] whether there is a buffer available or not once we start using the string to store stuff].

Edit2: As the comment explains, you can also have "hybrid" cases, where parts of a structure is being initialized, e.g. a struct that contains some elements of "plain data" and some elements that have constructors. The ones that have constructors will have their constructor called. The plain data will not be initialized.

1 It may well be that the code running constructors is part of, or called from inside the "main" function - but if that is the case, it will be "before any of your code in main is started".

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
Mats Petersson
  • 126,704
  • 14
  • 140
  • 227
  • 1
    +1 for taking a stab at it... it is hard to provide a precise definition of what and when will be initialized. The rules for initialization are complex and with a good amount of corner cases (for example, `struct S { int i; std::string s; };` does not have a user-provided constructor and is not a POD, and it will only be *partly* initialized if no initializer is provided for the instance. – David Rodríguez - dribeas Feb 08 '13 at 22:32
  • Yes, so `std::string` falls under "Anything not initialized by the constructor" [parts of a the string, such as length/size is initialized, but the string buffer may be just about anything the implementation likes - uninitilized, point to NULL, point to uninitialized data on heap, or something else]. – Mats Petersson Feb 08 '13 at 22:38
  • In the example above `std::string` will be *initialized* by the constructor (whatever the meaning of initialized that the implementor coded, which in the case of `std::string` is probably the whole thing), but the `i` is what will *not* be initialized. – David Rodríguez - dribeas Feb 08 '13 at 22:47
  • Will automatically generated default constructors initialize these members? – Drew Dormann Feb 08 '13 at 23:25
  • No, autamtically generated constructors don't initialize member variables of plain types. – Mats Petersson Feb 08 '13 at 23:27
2

From "Working Draft C++, 2012-11-02"

3.6.2 Initialization of non-local variables [basic.start.init]
2 Variables with static storage duration (3.7.1) or thread storage duration (3.7.2) shall be zero-initialized (8.5) before any other initialization takes place.

Variables with static storage are at least zero initialized.

3.7.3 Automatic storage duration [basic.stc.auto]
2 [ Note: These variables are initialized and destroyed as described in 6.7. — end note ]

6.7 says nothing about how automatic variables are initialized.

3.7.4 Dynamic storage duration [basic.stc.dynamic]
...
3.7.4.1 Allocation functions [basic.stc.dynamic.allocation]
... There are no constraints on the contents of the allocated storage on return from the allocation function. The order, contiguity, and initial value of storage allocated by successive calls to an allocation function are unspecified.

8.5 Initializers [dcl.init]
7 To default-initialize an object of type T means:
— if T is a (possibly cv-qualified) class type (Clause 9), the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
— if T is an array type, each element is default-initialized;
— otherwise, no initialization is performed.

If you provide an explicit initializer, any variable will have a known value.

If you don't provide an explicit initializer for a POD type, it depends on the storage class. Static or thread variables will be zero initialized, whereas automatic or dynamically allocated variables are not.

If you have a compound type, the same rules apply. If you have don't have an explicit initializer, through a (default) constructor or otherwise, the initial value of fundamental types depends on the storage class.

Finally, memory allocated through malloc will be uninitialized, whereas calloc memory will be zero initialized.

Olaf Dietsche
  • 72,253
  • 8
  • 102
  • 198
  • Except if I provide a no-argument constructor for a class, it's initialized using that constructor. So this is incomplete enough to be misleading. And I know that sometimes automatically generated default constructors will initialize things too, but I don't know under which circumstances that happens. – Omnifarious Feb 08 '13 at 22:44
  • 1
    @Omnifarious This is covered under `8.5 Initiailizers`. And the question is about POD types, not class types. – Olaf Dietsche Feb 08 '13 at 22:47