Static variables exist during the "lifetime" of the translation unit in which they are declared, and:
It cannot be accessible from any other translation unit if it is in a namespace scope (i.e. outside of functions and classes).
This is referred to as "internal linking" or "static storage lifetime."
(Except for constexpr, do not do this in headers; otherwise, you would wind up with a different variable in each translation unit, which is really confusing.)
If it is a variable in a function, it, like any other local variable, cannot be accessed from outside the function.
(This is the mentioned local)
Class members have no limited scope owing to static, but they may be referenced from both the class and an instance (like std::string::npos).
locations as code:
static std::string namespaceScope = "Hello";
void foo() {
static std::string functionScope= "World";
}
struct A {
static std::string classScope = "!";
};
Before any function in a translation unit is executed (possibly after main started execution), variables with static storage duration (namespace scope) in that translation unit are "constant initialised" (to constexpr where possible, or zero otherwise), and non-locals are "dynamically initialised" properly in the order they are defined in the translation unit (for things like std::string="HI"; that aren't constexpr).
Finally, when execution "reaches" the line where function-local statics are defined, they are initialised.
In the reverse sequence of initialization, all static variables are deleted.
The simplest approach to do this right is to convert any static variables that are not constexpr initialised into function static locals, which ensures that all of your statics/globals are properly initialised when you try to use them regardless of what, avoiding the static initialization order issue.
T& get_global() {
static T global = initial_value();
return global;
}
Be cautious, because while the standard specifies namespace-scope variables have "static storage duration" by default, they mean the "lifetime of the translation unit" bit, which does not exclude access outside of the file.
Functions
Significantly simpler, static is frequently used as a class member function and is only very seldom used for a free-standing function.
A static member function varies from a standard member function in that it may be called without an instance of a class, and since it lacks an instance, it cannot access the class's non-static members.
Static variables are useful when you need a function for a class that does not refer to any instance members, or for handling static member variables.
struct A {
A() {++A_count;}
A(const A&) {++A_count;}
A(A&&) {++A_count;}
~A() {--A_count;}
static int get_count() {return A_count;}
private:
static int A_count;
}
int main() {
A var;
int c0 = var.get_count(); //some compilers give a warning, but it's ok.
int c1 = A::get_count(); //normal way
}
A static free-function indicates that the function will not be referenced to by any other translation unit, allowing the linker to completely disregard it.
This serves only a few purposes:
Can be used in a cpp file to ensure that the function is never called from anywhere else.
If you place it in a header, each file will have its own copy of the function.
It's pointless since inline achieves the same thing.
Reduces labour to shorten connection time.
Each translation unit can have a function with the same name that does something different.
For example, you might include a static void log(const char*) in each cpp file, and they would all log in a different way