63

I have a namespace foo which contains an integer bar, declared so...

foo.h:

namespace foo {
    int bar;
}

Now if I include foo.h in only one file, this works just fine. But a problem arises when I include foo.h from two or more files: I get a linker error. I figured out that if I declare bar as static, I can include foo.h in more than one file. This seems strange to me, because I wasn't aware that one could declare a static variable inside of a namespace. (what does that even mean?)

Why does this work? And more importantly, why doesn't it work without static? What does static mean when used in a namespace?

Michael Dorst
  • 8,210
  • 11
  • 44
  • 71

4 Answers4

61

There are multiple meanings for static in different contexts. In this particular context it means that the variable has internal linkage, and thus each translation unit that includes that header will have it's own copy of the variable.

Note that while this will silent the linker error, it will do so maintaining a separate foo::bar variable for each one of the object files generated (changes will not be visible across different object files).

If you want a single variable, you should declare it as extern in the header and provide a single definition in one translation unit.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
43

When you declare a variable as static, it means that its scope is limited to the given translation unit only. Without static the scope is global.

When you declare a variable as static inside a .h file (within or without namespace; doesn't matter), and include that header file in various .cpp files, the static variable becomes locally scoped to each of the .cpp files.
So now, every .cpp file that includes that header will have its own copy of that variable.

Without the static keyword the compiler will generate only one copy of that variable, so as soon as you include the header file in multiple .cpp files the linker will complain about multiple definitions.

Michael Dorst
  • 8,210
  • 11
  • 44
  • 71
iammilind
  • 68,093
  • 33
  • 169
  • 336
  • 1
    But if the header has include guards, then the compiler will only include the header file once. In that case, is static and non-static variables the same? – Ben Butterworth Nov 28 '19 at 21:27
  • @ButterHub, include guards are during preprocessing stage to make sure that the file is included exactly once. While the static variable creation is during the compilation stage. After resolving include guards, wherever the header files are visible --> the static variables are created in all those .cpp files. – iammilind Nov 29 '19 at 03:50
  • but the header files are no longer visible in any C++ files after the preprocessor substitutes `#include "File.h"` with `File.h`'s contents. How does the compiler know to create the static variables for more than 1 file? (The first file will have the contents, but the include guard prevents more files from getting it?) – Ben Butterworth Nov 29 '19 at 09:27
  • 1
    @ButterHub, this might be difficult to explain in comments. You may create a test.h file with include guards and include in test1.cpp, test2.cpp, testN.cpp. Then compile them with -E option in g++ to see how the variable is declared in every .cpp file. e.g. "g++ -E test1.cpp > test1_show" – iammilind Nov 29 '19 at 11:44
  • 2
    Thanks @iammilind. My misunderstanding of what the preprocessor does with include guards was the issue. Even though include guard is present, code is substituted into *each* testX.cpp files once, if it is '#include''d. The include guards are there to protect double definition in the same file. – Ben Butterworth Nov 29 '19 at 13:35
7

The problem is caused by having more than one definition of the variable. The definitions in different translation units conflict with each other, just like multiple non-inline function definitions wouldn't work.

When you make the variable static you're giving the variable internal linkage, so each translation unit has its own independent copy.

What you probably actually want is to put only the declaration in a header (using extern) and then put the definition in an implementation file.

bames53
  • 86,085
  • 15
  • 179
  • 244
2

Also note that const int at namespace (global) scope in C++ has static implicitly added by default: Define constant variables in C++ header

To better understand what is going on, do a readelf on the intermediate ELF object files of the compilation, and you will see clearly is symbols are defined twice or not. Here is a detailed example: What does "static" mean in C?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985