Ultimately, there is no difference. Ignoring (for now) static member functions, static means what it means, but we see different parts of what it means in different conditions, because part of what it means can also happen without a keyword.
When you use the static , the designated object always has:
- static lifetime - it exists for the entire life of the program.
- local visibility - the name is not displayed outside the scope in which it is declared.
Both of these values โโrefer to a static variable, regardless of whether they are defined inside or outside the block. One part or the other will happen by default, even if you do not use the static , but if you use the keyword, you always get both.
static member functions are similar, but since they are functions, they do not have a lifetime, all functions have a static lifetime. A static member function has local visibility (that is, its name is visible only with its class) and something like a โstatic lifetimeโ - the function is not tied to an instance of the class.
Edit: for those interested in a specific time, when the static variable of the block level is inalistic, the gory details are as follows (ยง6.7 / 4):
Zero initialization (8.5) of all block volume variables with static storage duration (3.7.1) or thread storage duration (3.7.2) is performed before any other initialization. The constant initialization (3.6.2) of a block region object with a static storage duration, if applicable, is performed before its block is first entered.
Implementations are allowed to perform early initialization of other variables of the block area with static or storage streams of threads under the same conditions that implementations are allowed to statically initialize a variable with statics or storage duration of streams in the namespace space (3.6.2). Otherwise, such a variable is initialized when the first control passes through its declaration; such a variable is considered initialized after completion of its initialization.
Thus, the variable will be initialized to zeros very early when the program starts. Then, if another initialization is specified, this will happen no later than when the execution passes through the initialization (but may happen earlier than this). Note, however, the difference between constant initialization and other initialization. For example, consider something like this:
int g() { return 2; } int f() { goto bypass; static int x = 1; static int y = g(); bypass: std::cout << x << "\n" << y; }
Here x is an initialized constant, but y not. Since x is a constant initialization, it is initialized when entering a block, so when we print its value, we should get 1 . y , however, is not constant initialization, and goto means that execution never proceeds through its initialization, therefore it will save 0 , which was initialized before any other initialization occurred, therefore (with the correct working compiler), exit will be:
1 0