What makes a static variable initialize only once?

C++VariablesStaticStatic Variables

C++ Problem Overview


I noticed that if you initialize a static variable in C++ in code, the initialization only runs the first time you run the function.

That is cool, but how is that implemented? Does it translate to some kind of twisted if statement? (if given a value, then ..)

void go( int x )
{
    static int j = x ;
    cout << ++j << endl ; // see 6, 7, 8
} 

int main()
{
    go( 5 ) ;
    go( 5 ) ;
    go( 5 ) ; 
}

C++ Solutions


Solution 1 - C++

Yes, it does normally translate into an implicit if statement with an internal boolean flag. So, in the most basic implementation your declaration normally translates into something like

void go( int x ) {
  static int j;
  static bool j_initialized;

  if (!j_initialized) {
    j = x;
    j_initialized = true;
  }

  ...
} 

On top of that, if your static object has a non-trivial destructor, the language has to obey another rule: such static objects have to be destructed in the reverse order of their construction. Since the construction order is only known at run-time, the destruction order becomes defined at run-time as well. So, every time you construct a local static object with non-trivial destructor, the program has to register it in some kind of linear container, which it will later use to destruct these objects in proper order.

Needless to say, the actual details depend on implementation.


It is worth adding that when it comes to static objects of "primitive" types (like int in your example) initialized with compile-time constants, the compiler is free to initialize that object at startup. You will never notice the difference. However, if you take a more complicated example with a "non-primitive" object

void go( int x ) {
  static std::string s = "Hello World!";
  ...

then the above approach with if is what you should expect to find in the generated code even when the object is initialized with a compile-time constant.

In your case the initializer is not known at compile time, which means that the compiler has to delay the initialization and use that implicit if.

Solution 2 - C++

Yes, the compiler usually generates a hidden boolean "has this been initialized?" flag and an if that runs every time the function is executed.

There is more reading material here: https://stackoverflow.com/questions/898432/how-is-static-variable-initialization-implemented-by-the-compiler

Solution 3 - C++

While it is indeed "some kind of twisted if", the twist may be more than you imagined...

ZoogieZork's comment on AndreyT's answer touches on an important aspect: the initialisation of static local variables - on some compilers including GCC - is by default thread safe (a compiler command-line option can disable it). Consequently, it's using some inter-thread synchronisation mechanism (a mutex or atomic operation of some kind) which can be relatively slow. If you wouldn't be comfortable - performance wise - with explicit use of such an operation in your function, then you should consider whether there's a lower-impact alternative to the lazy initialisation of the variable (i.e. explicitly construct it in a threadsafe way yourself somewhere just once). Very few functions are so performance sensitive that this matters though - don't let it spoil your day, or make your code more complicated, unless your programs too slow and your profiler's fingering that area.

Solution 4 - C++

They are initialized only once because that's what the C++ standard mandates. How this happens is entirely up to compiler vendors. In my experience, a local hidden flag is generated and used by the compiler.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionboboboboView Question on Stackoverflow
Solution 1 - C++AnTView Answer on Stackoverflow
Solution 2 - C++JonView Answer on Stackoverflow
Solution 3 - C++Tony DelroyView Answer on Stackoverflow
Solution 4 - C++Jeffrey FaustView Answer on Stackoverflow