When are static C++ class members initialized?
Asked Answered
O

7

76

There appears to be no easy answer to this, but are there any assumptions that can be safely made about when a static class field can be accessed?

EDIT: The only safe assumption seems to be that all statics are initialized before the program commences (call to main). So, as long as I don't reference statics from other static initialization code, I should have nothing to worry about?

Oneiric answered 14/9, 2009 at 13:51 Comment(5)
makes me glad I do .net development now, where the answer is "just before you use them".Doublebank
I'd agree with your conclusion in the edit. The only sort of processing that's concurrent with static initialization is other static initialization. (Of course, that can be concurrent with other stuff the implementation does, but not anything you write.)Michiko
If you want to play that card, same thing in C++, except we only pay when we need it. :PMalacca
This post looks related: C++ - static variables initialisation orderHyperbaton
Here is a article talking about this, hopefully it helps: parashift.com/c++-faq-lite/static-init-order.htmlKierkegaard
A
69

The standard guarantees two things - that objects defined in the same translation unit (usually it means .cpp file) are initialized in order of their definitions (not declarations):

3.6.2

The storage for objects with static storage duration (basic.stc.static) shall be zero-initialized (dcl.init) before any other initialization takes place. Zero-initialization and initialization with a constant expression are collectively called static initialization; all other initialization is dynamic initialization. Objects of POD types (basic.types) with static storage duration initialized with constant expressions (expr.const) shall be initialized before any dynamic initialization takes place. 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.

The other guaranteed thing is that initialization of static objects from a translation unit will be done before use of any object or function from this translation unit:

It is implementation-defined whether or not the dynamic initialization (dcl.init, class.static, class.ctor, class.expl.init) of an object of namespace scope 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.

Nothing else is guaranteed (especially order of initialization of objects defined in different translation units is implementation defined).

Adolfoadolph answered 14/9, 2009 at 14:7 Comment(5)
What if I have a binary which has a 'main()' function and static are part of a library which is dynamically linked with binary. Does static initializes before main is called?Case
There's a contradiction in the above answer now, due to the EDIT. The second yellow box (quoting the standard) says "If the initialization is deferred to some point in time after the first statement of main()...", and you added "guaranteed to happen before main()" which contradicts it, and doesn't quote the standard.Lowery
"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." ---------- Then what's the point to not put the initialization before main() the only thing you can do without function/object is math ops.Moorefield
What if I perform a static initialization where the variable is NEVER used but it has a side effect (i.e, adds a key-value pair to a global registry)?Wu
"The other guaranteed thing is that initialization of static objects from a translation unit will be done before use of any object or function from this translation unit". Does this include the usage of the static object itself?Wu
K
28

They're initialized before the program starts (i.e. before main is entered).

When there are two or more definitions (of static data) in a single CPP file, then they're initialized in the sequence in which they're defined in the file (the one defined earlier/higher in the file is initialized before the next one is).

When there are two or more definitions (of static data) in more than one CPP file, the sequence in which the CPP files are processed is undefined/implementation-specific. This is a problem if the constructor of a global variable (called before the program is started) references another global variable defined in a different CPP file, which might not have been constructed yet. However, item 47 of Meyers' Effective C++ (which is titled Ensure that global objects are initialized before they're used) does describes a work-around ...

  • Define a static variable in a header file (it's static so you can have multiple instances of it without the linker complaining)

  • Have the constructor of that variable invoke whatever you need it to (in particular, construct the global singletons declared in the headers)

... which it says is a technique which may be used in some system header files e.g. to ensure that the cin global variable is initialized before even your static variables' constructors use it.

Kendra answered 14/9, 2009 at 14:1 Comment(2)
In the Effective C++ 3rd edition it is Item 4: Make sure that objects are initialized before they're used. (and there it talks about non-local static variables eg. static class members)Rotatory
Not all static objects are guaranteed to be initialized before main is entered. See Tadeusz Kopec's answer to this question which quotes the standard: "It is implementation-defined whether or not the dynamic initialization (dcl.init, class.static, class.ctor, class.expl.init) of an object of namespace scope is done before the first statement of main."Gratia
R
5

Your final conclusion in the Edit is correct. But the problem is the class static themselves. It's easier to say that my code will have class static members that don't refer to other global data/ class static members but once you take this route, things will go wrong soon. One approach that I have found useful in practice to not have class static data members but class static wrapper methods. These methods can then hold the static object within itself. For e.g.

TypeX* Class2::getClass1Instance()
{
    static TypeX obj1;
    return &obj1;
}

Note: An earlier answer says:

The other guaranteed thing is that initialization of static objects from a translation unit will be done before use of any object or function from this translation unit

This is not completely correct and the standard is incorrectly inferred here. This may not hold true if the function from a translation unit is called before main is entered.

Ravi answered 22/7, 2015 at 9:49 Comment(0)
H
1

I believe it can be accessed anytime during the execution. What remains undefined is the initialization order of the static variables.

Horwath answered 14/9, 2009 at 13:57 Comment(0)
N
1

They can be initialized in an implementation file (.c/cpp/cc) files. Dont initialize them in .h as compiler will complain about multiple definitions.

They are typically initialized before main, however order is uknown, hence avoid dependencies. They can certainly be accessed within member function. Keep in mind, order of initialization is unknown for static members. I would suggest to encapsulate a static member into the static function that will check if the member has been initialized.

Nancinancie answered 14/9, 2009 at 13:58 Comment(0)
U
0

There isn't a totally trivial answer to this question, but basically they're initialized just before control is passed to the entry point (main) of your program. The order in which they are initialized is (to my knowledge) undefined and may be compiler specific.

EDIT: To clarify, your added assumption is correct. As long as you're only accessing it post main-entry, you don't really have to worry about when/how it's initialized. It will be initialized by that time.

Unwrap answered 14/9, 2009 at 13:57 Comment(0)
F
-1

i think the main thread of a proccess will execute the following five steps in order

  1. initialization of CRT library

  2. static initialization

  3. execution of main() function

  4. static unitialization

  5. unitialization of CRT library

you want reference statics from other static initialization code? maybe the following codes work:

class A;
static auto_ptr<A> a(auto_ptr<A>(&GetStaticA()));
A &GetStaticA(void)
{
    static A *a = NULL; //the static basic type variables initialized with constant experession will be initialized earlier than the other static ones
    if (a == NULL)
    {
         a = new A();
         return *a;
    }
}
Fireboat answered 14/9, 2009 at 14:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.