Unfortunately the language does not support those semantics.
static storage duration objects SSDO (both static and dynamically initialized) are only guaranteed to be initialized before they are used. The standard has a description of the ordering constraints and guarantees in [basic.start.init]
.
The following describeshow dynamic initialization may be deferred until after main.
(n2723) 3.6.2 Initialization of non-local objects [basic.start.init]
paragraph 4
It is implementation-defined whether or not the dynamic initialization (8.5, 9.4, 12.1, 12.6.1) of an object of namespace scope with static storage duration is done before the first statement of main. If the initialization is deferred to some point in time after the first statement of main, it shall occur before the first use of any function or object defined in the same translation unit as the object to be initialized.
In practice, as long as your object have no side affects, then you can write your code as if they were all initialized before main (as an attempt to access them will cause their initialization (no explicit action is required by your code)). If they have side affects then don't rely on the side affects happening.
If you rely on the side-effects then you can take advantage of main()s location.
Just declare all SSDO objects in the same file as main(). Because they are in the same translation unit they must now all be initialized before main is entered.
It is written this way (or one of the reasons) to allow the usage of dynamically loading shared libraries (dll) without explicitly having the concept of shared libraries written into the standard. As a dynamically loaded shared library is not present in the executable before main() is entered it can not have its SSDO initialized before main(). The above part of the standard allows for this fact. Though it does guarantee that any SSDO will be initialized before they are used.
Shared Libraries
Of course nothing about shared libraries (dll) is defined in the standard as these components are not tied directly to the language but are a feature provided by the OS.
That being said. Most OS's when they load a shared library (through the standard shared library loading mechanism ie. dlopen()) will initialize all SSDO before the function call to load the shared library returns. In situations where SSDO initialization is deferred it will obey the rule defined above in [basic.start.init]
.
Order of Initialization:
The order of initialization is not usually important.
Unless you use a SSDO during the initialization (or destruction) of another SSDO. Then order does become important as you need to make sure that the used object has been created/initialized before it is used (otherwise its data is garbage).
You have a couple of options. If the SSDO are in the same translation unit, you can define there initialization order by the order they are declared in the translation unit:
// File OneFile.cpp
myClass2 gv_2 = some_othere_global_function();
myClass1 gv_1 = some_global_function(); // If this uses gv_2 it must be declared first
If they are in different translation units then you have no guarantees about the order:
// File 1.cpp
myClass1 gv_1 = some_global_function(); // If this uses gv_2 you may have a problem.
// File 2.cpp
myClass2 gv_2 = some_othere_global_function();
The order problem can be solved by using a function:
// File 1.cpp
myClass1& get_gv_1()
{
static myClass1 gv1 = some_global_function(); // This function can only access gv2
// by calling get_gv_2(). This will of
// force dynamic creation of the object
// this it is guaranteed to be initialized.
return gv1;
}
// File 2.cpp
myClass2& get_gv_2()
{
static myClass2 gv2 = some_othere_global_function();
// ^^^^^^
// Notice the use of static here.
// This means the object is created the first time the function
// is called (and destroyed on application exit).
//
// All subsequent calls will just use the same value.
// Note the return type. We return a reference to the object.
return gv2;
}
Also see: