If you change the initialization of cMyConstDouble2
to this here:
const double cMyConstDouble2 = 2.5*3.14;
Then your program should behave correct. The reason for this is that variables that
- Have POD type
- Are initialized with constant expressions (1)
are initialized at static initialization time. These initializations include
- Zero initialization of all objects having static storage duration
- Initializations of PODs initialized with constant expressions
Of your shown variables, only cMyConstDouble
satisfies both conditions of being fully initialized at static initialization time. However, cMyConstDouble2
does not, since its initializer does not satisfy the requirements of a constant expression. In particular, it includes a variable that doesn't have integral type (here, it has floating point type). However, floating point literals *are* allowed in arithmetic constant expressions. That is why 2.5*3.14
is an arithmetic constant expression. And that is why changing the initializer to that will require it to be statically initialized.
What will happen with cMyConstDouble2
if you stay with the non-constant expression? The answer is, you don't know. The Standard allows that variable to be statically initialized, but does not require it to do so. In your case, it was dynamically initialized - thus its value just after static initialization time was still zero. To get a feeling for how complicated that is, here is an example:
inline double fd() { return 1.0; }
extern double d1;
double d2 = d1; // unspecified:
// may be statically initialized to 0.0 or
// dynamically initialized to 1.0
double d1 = fd(); // may be initialized statically to 1.0
If the dynamic initialization doesn't change any other static storage variable (satisfied in your code) and when the static initialization would produce the same value as would be produced by dynamic initialization when all objects not required to be statically initialized would be initialized dynamically (also satisfied in your code) - then the variable is allowed to be initialized statically. These two conditions are also satisfied in the above code for both variables d2
and d1
:
Analysis of d2
= d1
does not change any other static storage variable
- When both
d2
and d1
are initialized dynamically, then d2
would be initialized to 0.0
, because d2
is defined before d1
, and dynamic initialization of d2
would grab the value of d1
as of the state just after static initialization (where only zero initialization of d1
took place).
Analysis of d1
= fd()
does not change any other static storage variable
- When both
d2
and d1
are initialized dynamically, then = fd()
will initialize d1
to 1.0
.
So, the compiler may initialize d1
statically to 1.0
, because both conditions for optional-static-initialization are met.
If the compiler decides to initialize d1
and d2
dynamically, then d2
will be initialized to 0.0
, since it will grab the value of d1
as it was just after zero initialization.
However, if the compiler decides to initialize d1
statically and d2
dynamically, then d2
will be initialized to 1.0
, since the dynamic initialization of d2
will grab the fully initialized value of d1
as it was just after static initialization.
I'm not sure what the value of d2
is when d1
and d2
is initialized statically, though. That is, whether d2
is supposed to grab the 0.0
or the 1.0
, since there is no order defined for static initialization.
(1) Constant expressions include arithmetic constant expressions too (not only integral constant expressions), when considering initialization order of objects with static storage duration.