Is it true that order of Static Initialization is implementation defined?
I see pretty confused answers so let me summarize: NO, STATIC INITIALIZATION ORDER IS NOT IMPLEMENTATION DEFINED.
Let's see why and in which cases. According to your quote let me assume you're asking about (static or dynamic) initialization of non-local variables static storage duration.
C++ standard §9.4.2 (paragraph 6) says:
Static data members are initialized and destroyed exactly like non-local variables.
Then according to §3.6.2 and §3.7.1 no, [order] within a compilation unit is not implementation defined but it always follows declaration order (as described in §6.7 paragraph 4):
Variables with ordered initialization defined within a single translation unit shall be initialized in the order of their definitions in the translation unit.
Rules for static and dynamic initialization are the same and they're described in same paragraph, the only (remarkable) difference between static and dynamic initialization is ordering, static initialization will always occurs before dynamic initialization and dynamic initialization may be unordered.
Together, zero-initialization and constant initialization are called static initialization; all other initialization is dynamic initialization. Static initialization shall be performed before any dynamic initialization takes place.
How static initialized non-local variables are initialized is described in paragraphs 1 and 2 from §3.6.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. Constant initialization is performed...[omitted]
According to comments I need to clarify this point: a non-local static variable may have thread storage duration specifier thread_local
(then it'll behave like a static
variable from user POV nut they also be combined). It's still eligible for static initialization (then ordered and then it must obey to above rule) but initialization can't be performed simply loading data segment from disk. Code must be executed (TlsAlloc
on Windows) but from standard POV it's still a static initialized expression (first zero-initialized and then with constant initialization). Let's see a very fictional example:
thread_local unsigned int _value = 1;
Now let's try to imagine how compiler may implement that. We can start with something known and imagine a behavior similar to boost::thread_specific_ptr
. Implementation on Windows (but it's pretty similar on Windows too) will need to call TlsAlloc
when thread is initialized and TlsFree
when thread is finished. You'll access variable normally but probably it'll implemented as a pointer with an offset from memory allocated by TlsAlloc
. The only thing that will come from executable file on disk is initial value (and again it's just an implementation detail who you shouldn't care). Initial value (as described before) will be 0 (for unsigned int
). Given all this code, these function calls and so many details...probably it's still eligible to be considered constant initialization because requirements imposed by standard are fulfilled then compiler should (may) respect them. It means it may be static initialized. To summarize:
- Standard says that static initialized variables will respect declaration order.
- Standard says when variables are dynamically initialized and when statically initialized.
- Standard does not say where that values should come from at run-time.
- Standard does not say how implementation should initialize them.
Of course inside a single function same rule apply but declaration should be replaced with usage (§6.7 ) but this isn't your question.
Order for different compilation unit is not granted and it's implementation defined (but there are techniques to make this order arbitrary then predictable: Nifty Counter and variables aggregation, for example).