3 Basic concepts [basic]

3.6 Start and termination [basic.start]

3.6.3 Dynamic initialization of non-local variables [basic.start.dynamic]

Dynamic initialization of a non-local variable with static storage duration is unordered if the variable is an implicitly or explicitly instantiated specialization, is partially-ordered if the variable is an inline variable that is not an implicitly or explicitly instantiated specialization, and otherwise is ordered. [ Note: An explicitly specialized non-inline static data member or variable template specialization has ordered initialization. — end note ]

Dynamic initialization of non-local variables V and W with static storage duration are ordered as follows:

  • If V and W have ordered initialization and V is defined before W within a single translation unit, the initialization of V is sequenced before the initialization of W.

  • If V has partially-ordered initialization, W does not have unordered initialization, and V is defined before W in every translation unit in which W is defined, the initialization of V is sequenced before the initialization of W if the program does not start a thread ([intro.multithread]) and otherwise happens before the initialization of W.

  • Otherwise, if a program starts a thread before either V or W is initialized, the initializations of V and W are unsequenced.

  • Otherwise, the initializations of V and W are indeterminately sequenced.

Note: This definition permits initialization of a sequence of ordered variables concurrently with another sequence.  — end note ]

It is implementation-defined whether the dynamic initialization of a non-local non-inline variable with static storage duration happens before the first statement of main. If the initialization is deferred to happen after the first statement of main, it happens before the first odr-use ([basic.def.odr]) of any non-inline function or non-inline variable defined in the same translation unit as the variable to be initialized.36Example:

// - File 1 -
#include "a.h"
#include "b.h"
B b;
A::A(){
  b.Use();
}

// - File 2 -
#include "a.h"
A a;

// - File 3 -
#include "a.h"
#include "b.h"
extern A a;
extern B b;

int main() {
  a.Use();
  b.Use();
}

It is implementation-defined whether either a or b is initialized before main is entered or whether the initializations are delayed until a is first odr-used in main. In particular, if a is initialized before main is entered, it is not guaranteed that b will be initialized before it is odr-used by the initialization of a, that is, before A::A is called. If, however, a is initialized at some point after the first statement of main, b will be initialized prior to its use in A::A.  — end example ]

It is implementation-defined whether the dynamic initialization of a non-local inline variable with static storage duration happens before the first statement of main. If the initialization is deferred to happen after the first statement of main, it happens before the first odr-use ([basic.def.odr]) of that variable.

It is implementation-defined whether the dynamic initialization of a non-local non-inline variable with static or thread storage duration is sequenced before the first statement of the initial function of the thread. If the initialization is deferred to some point in time sequenced after the first statement of the initial function of the thread, it is sequenced before the first odr-use ([basic.def.odr]) of any non-inline variable with thread storage duration defined in the same translation unit as the variable to be initialized.

If the initialization of a non-local variable with static or thread storage duration exits via an exception, std::terminate is called ([except.terminate]).

A non-local variable with static storage duration having initialization with side effects must be initialized even if it is not odr-used ([basic.def.odr], [basic.stc.static]).