Goodies and others are certainly correct, but let me put one more step ahead:
static
makes the definition local to the translation unit. So defining a static global variable in the header will result in as many copies as the translation units it is included. Unless that's not specifically what you want that's not the way
extern
tells the compiler that the global variable exist somewhere, but is not defined and must be searched at link phase. To the linker to succeed, you need to define it somewhere (typically a source file where it make more sense to exist)
Omitting both of them will result in a "multiple definition" linker error, where more than one source includes an header.
Now, the 2nd case has two limitation:
- it forces you to have a compilable source to instantiate a global object even in the case you are providing a template library (or an "header only" library) making delivery more complex as required
- It exposes to the so called global initialization fiasco: if you initialize a global object with values taken from other global objects defined elsewhere, since C++ doesn't grant about their order of construction (that ultimately belongs to the way the linker works), you may have trouble in proper initialization and destruction of global objects.
To avoid all this, consider that
- A global defined function, if explicitly declared as
inline
can be linked more times and
- Template functions as well as in-class defined member functions are in-lined by default
- static local object are created only once, the first time they are encountered
You can define global values in headers by making them static local to functions: like in
inline int& global_val() //note the &
{ static int z = 0; return z; }
the only drawback is that you have always to place a ()
upon every access.
Since the local value is unique and instantiated upon a call, this will ensure that, if there are dependencies between globals (think to int z=0
as int z=something_else()
) they will be created in the order they are needed and destroyed in reverse order, even in case of recursion and multiple threads (since c++14)
Considering the evolution of C++ towards generics and functional paradigms, and considering that placing all sources in a single compilation unit is sometime preferable than linking many sources... Have a think about not using global variables, but replacing them with inlined instatiator functions.
Editing about 2 years later:
C++17 have finally introduced the inline directive for also for variable declarations, just as a syntactic shortcut to the function expansion.
So -today- you can simply write
inline const float PI = 3.14159;
inline int goodies = 25;