I had this posted as request for clarification in another thread, but it deserves a thread of its own, I think.
The question is basically - under what circumstances the compiler can perform early initialization of static local variables. I though that the perceived order of initialization (from the programmer's perspective) is never influenced by the actual order of initialization that the compiler chooses. But certain posts over the internet left me with a doubt.
6.7/4:
... An implementation is permitted to perform early initialization of other local objects with static storage duration under the same conditions that an implementation is permitted to statically initialize an object with static storage duration in namespace scope (3.6.2). Otherwise ... |
So off we go to 3.6.2.
3.6.2/1:
... Zero-initialization and initialization with a constant expression are collectively called static initialization; all other initialization is dynamic initialization. Objects of POD types (3.9) with static storage duration initialized with constant expressions (5.19) shall be initialized before any dynamic initialization takes place. ... |
I understand that certain
forms of initializing expressions are called static initialization, and some dynamic initialization. I am not certain what is the meaning of constant expression in this context. Specifically, look at my example at the bottom.
3.6.2/2 (part 1):
An implementation is permitted to perform the initialization of an object of namespace scope with static storage duration as a static initialization even if such initialization is not required to be done statically, provided that |
Was the term "static initialization" used in a different sense in the previous paragraph? Is it a kind of initializing expression or variety of initialization procedure?
3.6.2/2 (part 2):
— the dynamic version of the initialization does not change the value of any other object of namespace scope with static storage duration prior to its initialization, and |
Well, is it just me (be kind :) or "the initialization...prior to its initialization" expression is oxymoron. Does "the initialization" include the construction of the object or only the calculation of the initializer expression (construction arguments)? My point is, are side-effects from the constructor considered in this clause?
3.6.2/2 (part 3):
— the static version of the initialization produces the same value in the initialized object as would be produced by the dynamic initialization if all objects not required to be initialized statically were initialized dynamically |
The same as above. What about side effects inside the constructor?
In fact, the compiler implementer can always change any behavior as he chooses, as long as there is no significant (say performance-wise) perceived effect. This is implicit. Is there anything that this clause states, besides reassert this fact?
For example, in the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
bool flag;
int f()
{
if (!flag) flag = true;
return 5;
}
struct S {
S(int)
{
if (!flag) flag = true;
}
};
int main()
{
static S s1 = 5; //is this constant initializing expression?
static S s2(5); //is this constant initializing expression?
static S s3 = S(5); //is this constant initializing expression?
static S s4 = f();
}
|
I assume that the perceived order and actual order in which those initializations are performed is the same, because they are (contrary to good practice) highly dependent on global data and modify global data.
Is there any doubt regarding the order in which those initializations are performed/attempted? Can they be performed before main (with the OS rebooting respectively)? Which of those are considered "initalized with constant expressions"?
Thanks