"Old Wolf" <
XXXX@XXXXX.COM >writes:
Quote
I read the text again, it is quite convoluted. I think what it is
saying is that for local static non-POD, it should be initialized
the first time that execution reaches the declaration. However,
if there are no side-effects of initialization then it can be
done earlier.
I think you're right, except that it must be initialized before the
code is reached. Since constructors can throw, this "early"
initialization might not be a good idea, except when the compiler can
also prove that the code cannot throw.
(For static local objects that throw in their constructor, the next
time the function is called, the object will be attempted to be
initialized again, and so on, until the constructor succeeds.)
The early initialization is a nice feature when it can be implemented,
though, because the generated code can be much more efficient. The
static local variables not only need space for the object, but also
need a "flag" to indicate whether they've been initialized. This flag
is checked every time the function is called:
This:
void foo()
{
static MyObject obj;
//...
}
Would become equivalent to something like this:
static char vfoov_MyObject_foo[sizeof MyObject];
static bool vfoov_MyObject_foo_initialized = false;
void foo()
{
if ( ! vfoov_MyObject_foo_initialized )
{
new (vfoov_MyObject_foo) MyObject;
vfoov_MyObject_foo_initialized = true;
}
// ...
}
and then sometime in the cleanup code for that translation unit:
//...
if (vfoov_MyObject_foo_initialized)
{
vfoov_MyObject_foo.~MyObject();
}
(Note, I made them file-scoped statics because those have internal
linkage, and nobody in any other translation unit would need to see
the defintion of the static locals. The standard usually doesn't say
things about the implemention of features, and so this is not strictly
required, but how I'd do it were I writing the compiler. However, had
the function been inlined, it would have needed global access to the
data, since each inlined expansion of the function would need to view
the same memory, across translation units.)
If the compiler can prove that the object's construction cannot fail
and has no side effects, then it can simplify the generated code a
lot:
// initialized at normal program startup like any other "regular"
// global variable, except it's not directly accessible by the
// program code like global variables are.
static MyObject vfoov_MyObject_foo;
void foo()
{
// ...
}
The runtime benefit is that it can avoid all the checks to see if it's
initialized or not, and save storing the flag entirely. It's more
efficient in both runtime performance and storage requirements.
--
Chris (TeamB);