c++c++17initialization-orderinline-variable

When are inline variables in static storage initialized?


C++ standards (earlier than C++17, at least) have said this about initialization order.

Objects with static storage duration defined in namespace scope in the same translation unit and dynamically initialized shall be initialized in the order in which their definition appears in the translation unit.

C++17 introduces inline variables, which I believe to mean that a single variable with static storage duration and namespace scope and dynamic initialization could be defined in multiple translation units.

Does C++ make any guarantees about the initialization order of these variables?


Solution

  • See [basic.start.dynamic] p1:

    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.

    Therefore, the type of variable you are describing has "partially-ordered initialization". According to p2:

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

    • ...
    • 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, then
      • if the program starts a thread (4.7) other than the main thread (6.6.1), the initialization of V strongly happens before the initialization of W;
      • otherwise, the initialization of V is sequenced before the initialization of W.
    • ...

    So to summarize, assuming that there are no instantiated templates in the picture:

    An intuitive way to think about initialization order is that, just as in C++14, the compiler initializes each translation unit in order, with the relative ordering of different translation units unspecified (and they can be interleaved with each other), but an inline variable with external linkage is considered to be initialized the first time the implementation "hits" one of its definitions which may be in any translation unit.

    Also see p5:

    It is implementation-defined whether the dynamic initialization of a non-local inline variable with static storage duration is sequenced before the first statement of main or is deferred. If it is deferred, it strongly happens before any non-initialization odr-use of that variable. It is implementation-defined in which threads and at which points in the program such deferred dynamic initialization occurs.