Is the order of file-level static variables always the same within a given translation unit?

392 views Asked by At

I have a program split up into two source files:

example.cpp

#include <iostream>

class A {
 public:
   A(int x) {
      ::std::cout << "In A(" << x << ")\n";
   }
};

static A first(1);
static A second(2);

example__main.cpp

int main(int argc, const char *argv[])
{
   return 0;
}

Is the output of this program guaranteed to be:

In A(1)
In A(2)

on all platforms and compilers? If so, where in the standard does it say this? Does it matter if I'm using namespaces and first and second appear in different namespaces? How about if they aren't static and I'm using an anonymous namespace?

2

There are 2 answers

0
cpx On BEST ANSWER

Yes, the order of initialization is defined for non-local static objects if the declarations appear in the same translation unit.

From C++03,

(3.6/2) 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. [Note: 8.5.1 describes the order in which aggregate members are initialized. The initial-ization of local static objects is described in 6.7. ]

9
Kerrek SB On

Within one translation unit, global variables are initialized in several stages:

  • First, all variables that have "static initialization" are initialized in their order of declaration (see below).

  • Then, all "ordered dynamic initializations" are performed, again in their order of declaration.

  • There are also "unordered dynamic initializations", which are "unsequenced" with respect to the other dynamic initializations (but always after the static ones).

Destruction of statically and ordered-dynamically initialized globals proceeds in opposite order (and the unordered ones again "unsequenced", but before the static ones). The relative initialization ordering across TUs is unspecified.

To explain the terminology loosely: a global variable is "statically initialized" if it is either initialized to a constant (for constructor calls, this requires constexpr constructors), or if it is has no initializer and is declared static (which makes it zero-initialized): static int a; Foo b(1, true, Blue); On the other hand, if the initializer is not anything "constant", like a function call or a non-constexpr constructor, then the object is "dynamically initialized". Most ordinary globals that are dynamically initialized are "ordered"; the only "unordered" ones are static members of template specializations and such like.

(Note that all this got a lot more detailed in C++11, as there is now explicit attention to thread-local storage and initialization at the start of a thread.)