全域性變數、類靜態變數及函式區域性靜態變數的初始化順序
What is the lifetime of class static variables in C++?
First the list of possibilities.
- Namespace Static
- Class Static
- Local Static
Namespace Static
- There are two initialization methods. static (intended to happen at compile time) and dynamic (intended to happen at runtime) initialization.
- Static Initialization happens before any dynamic initialization, disregarding of translation unit relations.
- Dynamic Initiaization is ordered in a translation unit, while there is no particular order in static initialization. * Objects of namespace scope of the same translation unit are dynamically initialized in the order in which their definition appears.
- POD type objects that are initialized with constant expressions are statically initialized. Their value can be relied on by any object’s dynamic initialization, disregarding of translation unit relations.
If the initialization throws an exception,
std::terminate
The following program prints A(1) A(2)
struct A {
A(int n) { std::printf(" A(%d) ", n); }
};
A a(1);
A b(2);
And the following, based on the same class, prints A(2) A(1)
extern A a;
A b(2);
A a(1);
Let’s pretend there is a translation unit where msg
is defined as the following
char const *msg = "abc";
Then the following prints abc
. Note that p receives dynamic initialization. But because the static initialization (char const*
is a POD type, and "abc"
is an address constant expression) of msg
happens before that, this is fine, and msg
is guaranteed to be correctly initialized.
extern const char *msg;
struct P { P() { std::printf("%s", msg); } };
P p;
- Dynamic initialization of an object is not required to happen before main at all costs. The initialization must happen before the first use of an object or function of its translation unit, though. This is important for dynamic loadable libraries.
Class Static
- Behave like namespace statics.
- There is a bug-report on whether the compiler is allowed to initialize class statics on the first use of a function or object of its translation unit too (after main). The wording in the Standard currently only allows this for namespace scope objects - but it seems it intends to allow this for class scope objects too. Read Objects of Namespace Scope.
- For class statics that are member of templates the rule is that they are only initialized if they are ever used. Not using them will not yield to an initialization. Note that in any case, initialization will happen like explained above. Initialization will not be delayed because it’s a member of a template.
Local Static
- For local statics, special rules happen.
- POD type objects initialized with constant expression are initialized before their block in which they are defined is entered.
- Other local static objects are initialized at the first time control passes through their definition. Initialization is not considered to be complete when an exception is thrown. The initialization will be tried again the next time.
Example: The following program prints
0 1
:
struct C {
C(int n) {
if(n == 0)
throw n;
this->n = n;
}
int n;
};
int f(int n) {
static C c(n);
return c.n;
}
int main() {
try {
f(0);
} catch(int n) {
std::cout << n << " ";
}
f(1); // initializes successfully
std::cout << f(2);
}
In all the above cases, in certain limited cases, for some objects that are not required to be initialized statically, the compiler can statically initialize it, instead of dynamically initializing it. This is a tricky issue, see this answer for a more detailed example.
Also note that the order of destruction is the exact order of the completion of construction of the objects. This is a common and happens in all sort of situations in C++, including in destructing temporaries.