static Member Variables

Good Old C: extern Global Variables

  • Declaration (and usage)

    • Hey compiler, please don’t care: the linker will bring that in. Not your business.

    • Hey linker, insist in bringing that in: find it in all the other compilation units. But only if it is “odr-used” (i.e., if it is referenced)

    #include <stdio.h>
    
    extern int global;               // <--- "extern" declaration
    
    int main(void)
    {
        printf("%d\n", global);
        return 0;
    }
    
  • Definition

    • Hey linker, if someone outside needs that, please happily offer it.

    int global = 42;                 // <--- definition: allocates memory in .bss
    

ODR: One Definition Rule

  • A variable must be defined at most once

  • Can be left undefined if not used (⟶ odr-used)

Duplicate definition*

int global = 666;
double global = 42.7;
int main()
{
    return 0;
}

Left undefined if unused*

extern int global;

int main()
{
    return 0;
}

(A Litte) More Overengineered: Declaration In Header File

  • Declaration and definition always pairwise: header file and c file

  • Don’t place extern declaration directly at the user’s site

  • ⟶ Use a header file

    #pragma once
    
    extern int global;
    
  • As above, .c file defines it (including .h file only for type sanity checks)

    #include "extern-declaration.h"
    
    int global = 666;
    
  • Using entity (main()) include .h to pull in extern declaration, and to odr-use the variable

    #include <stdio.h>
    
    #include "extern-declaration.h"
    
    int main(void)
    {
        printf("%d\n", global);
        return 0;
    }
    

Same Inside A Class: static Member Variable

  • extern declaration, only prettier

    #pragma once
    
    class Class
    {
    public:
        static int global;        // <--- "extern" declaration
    };
    
  • Definition: same, only inside class

    #include "class-good-old.h"
    
    int Class::global = 42;        // <--- definition
    
  • Using entity, again. Not much different.

    #include "class-good-old.h"
    
    #include <iostream>
    using namespace std;
    
    int main()
    {
        cout << Class::global << endl;
        return 0;
    }
    

Sideway: Definition In A Header File?

  • Definition of static class member not possible

  • C++ appears to enforce the ODR

class Class
{
public:
    static int global = 666;
};
error: ISO C++ forbids in-class initialization of non-const static member ‘Class::global’
    7 |     static int global = 666;        // <--- "extern" declaration
      |                ^~~~~~

static inline Member Defnition (Since C++17)

  • Major trickery from C++ 17 onwards

  • ODR definition in class definition

    • ⟶ no .cpp file anymore to satisfy ODR

  • Immune to multiple includers of the class

    • … which is the regular case

    • Burden placed upon the linker

#pragma once

class Class
{
public:
    static inline int global = 42;      // <--- **definition!!**
};