Does each file get its own copy of the static variable? - c++

Suppose you have a static global variable in your header file, and you use this variable in your main.cpp.
// header.h
static int variableOne = 100;
//main.cpp
.
.
cout << variableOne << endl;
Will main.cpp get its own copy of variableOne (although the value is still 100...)? Or am I mixing this concept with extern (I know that extern tells the compiler that variableOne is defined elsewhere in the project...)
Thank you.

If you declare a static variable in an header file then a copy of that variable will be created in each translation unit where you include the header file.
So Never declare a static variable in Header File.
Also, C++03 standard: 7.3.1.1/2 says:
The use of the static keyword is deprecated when declaring objects in a namespace scope, the
unnamed-namespace provides a superior alternative.
C++03 standard: 7.3.1.1/1 says:
"[a]lthough entities in an unnamed namespace might have external linkage, they are effectively qualified by a name unique to their translation unit and therefore can never be seen from any other translation unit."
In simple words, an unnamed namespace restricts the visibility of its members to the scope of the translation unit by means of name mangling and avoids the problems faced as while using static keyword.
Also, You cannot use keywords static and extern together on a variable because both aim to achieve mutually exclusive behaviors.

In this case, each compilation module will get it's own copy of the variable.
If you use extern, there will only be one copy. But you are only allowed to initialize it in one module.
In other words, if you just replace static with extern in your example, it won't compile because it's being initialized in every module that includes that header.

1. What does it mean #include
When you write #include "header.h" the compiler is basically just copying the whole content of the file instead of that line. In C++ an header file has no semantic meaning, it's just used for textual substitution.
So if you have
---- header.h ----
static int variableOne = 100;
---- main.cpp ----
#include "header.h"
...
std::cout << variableOne << std::endl;
for the compiler is exactly the same as
---- main.cpp ----
static int variableOne = 100;
...
std::cout << variableOne << std::endl;
2. What does it mean static in that context
A static variable is like a global for the lifetime (i.e. it's constructed before main starts and it's destroyed after main terminates) but is only visible inside the translation unit that defines it. So you can have the same static variable name used in different translation units and all those variables are distinct (each translation unit will see its own static variable).
3. What happens when you put a static variable declaration in an header?
The net result is that every translation unit that will include that header will get its own static variable with that name because it's exactly the same as if the translation unit defined a static variable in the .cpp and not in the header file.
The name will be the same for all of them but they will be different variables. Of course if the header file declares and initializes the variable then the initial value will be the same, but all those variables will be distinct and if for example one translation unit changes that variable, the change will not be seen by other translation units.

Each source file would get their own independent copy of variableOne.
The last use of static is as a global variable inside a file of code.
In this case, the use of static indicates that source code in other
files that are part of the project cannot access the variable. Only
code inside the single file can see the variable.
Source
If you use extern all your source files will reference the same variable, but you won't be able to initialize it in the header. You would have to add an initialization to one of the source files.

static variables in namespace scope are not external, and as such you would get a copy of the static variable for each 'translation unit' in the project. This technique has been obsoleted since C++03, and the recommended way to do it is now enclosing the variable within an unnamed namespace.

Related

c++ strange behavior of static function with static variables

I am trying to create bunch of void methods and call them later in program.
I will demonstrate the code ahead to help better understand my issue.
.h file
static float sfloat;
namespace someNamespace
{
static void foo();
}
.cpp file
void someNamespace::foo(){cout<<sfloat<<endl}
above code is simpler version of class that I was working on.
I initialize sfloat in other .cpp file
otherFile.cpp
void initializeAndUseFoo(){sfloat = 5; someNamespace::foo();}
As far as my understanding goes, I expect foo to print out 5 but it prints out 0 instead.
This behavior occurs across all other static variables that I have as well(pointer included). It seemed that somehow the variables inside the function are never initialized as the value I assign.
However if I call out "sfloat" not through the function then I can call it out properly.(if I just print it out on console with just
cout<<"just print it not through the function : " <<sfloat<<endl;
then it is indeed 5
Thank you for reading.
A global static variable is static within one compilation unit. If you make another compilation unit, it will have a separate copy of that static variable.
This SO question explains what a compilation unit is in C++.
Since your variable is static and global in the same time, there will be a single instance of it in it's compilation unit. If you want to access that exact variable from another file, you will have to use the extern keyword. Without it, a new copy of that variable will be created in each compilation unit. You can find some information here, for example.
That's not a class, it's a namespace. static inside the namespace or at global scope gives methods and variables internal linkage. That means a copy of each will be available for each translation unit.
Because you modify (not initialize) sfloat in otherFile.cpp, only that version of the variable is modified. The original, initialized in .cpp file, retains the same value (which is the version printed by someNamespace::foo().

Okay to declare static global variable in .h file?

static keyword keeps the scope of a global variable limited to that translation unit.
If I use static int x in a .h file and include that .h file every other file, won't they all belong to the same translation unit?
Then, won't x be visible everywhere?
So what is the role of static now?
Also, is there any use of static const int x ,where x is a global variable?
Aren't all const global variables static by default?
And is a const variable's scope limited to the TU even if it confined in a for loop in the file?
If you write
static const int x
in an .h file then every translation unit that #include-s this .h will have its own private variable x.
If you want to have 1 global variable visible to everyone you should write
extern const int x;
in the .h file and
const int x = ...;
in one of the .cpp files.
If you want to have a static const int visible to just one translation unit - don't mention it in the .h files at all.
If I use static int x in a .h file and include that .h file every
other file, won't they all belong to the same translation unit?
If you declare something as static (not inside a class, for class static keyword has a different semantic), that static variable cannot be seen outside its TU. So putting it in the header file will cause each TU including that header to have a different private copy of that static variable.
And is a const variable's scope limited to the TU even if it confined
in a for loop in the file?
NO. Even for a static const value, the scope is determined by it's declaration. So the scope will be limited by your for brackets.
you will end up will private copies of that variable per translation, which will result in bloat if you put it there. it would also make no sense to have to random copies all over the place. no it's not ok.
you can declare a const int in a namespace block; that's ok.
The observable difference for variables that are const qualified is that in the static version you will get one copy per translation unit and so address comparisons of two such copies may fail.
If you never use the address of your const variable any modern compiler should be able to just use the value and optimize the variable itself out. In such a case a static const-qualified variable is completely fine.
Basically, each source file together with all included header files is a single translation unit. So If you have a static variable in a header file then it will be unique in each source file (translation unit) the header file is included in.
"static global" doesn't make sense, they are in a way each other's opposites.
The term "global" is often misused to describe a variable declared outside any function at file scope. But rather, a global variable is one with external linkage, that can be accessed by any file in the project - hence global.
The opposite of external linkage is internal linkage, which means that a variable can only get accessed by the translation unit where it is declared. Translation unit meaning one .c file and all the headers included by it (recursively).
static is a guarantee that a variable gets internal linkage. Thus other translation will not be able to access it or declare extern variables referring to it.
What happens if you declare a static variable in a header file is that more than one translation unit will get a separate variable with that name. The code will compile fine, although clever linkers will notice this and give a linker error. These kind of linker errors are often non-descriptive and hard to track down.
This leads us to the following best practices:
Never declare any variables inside a header file, as this often creates subtle bugs and linker errors.
To prevent such bugs, always surround all header files with "header guards":
#ifndef MYHEADER_H
#define MYHEADER_H
/* contents of header */
#endif
All variables declared at file scope should be declared static, for the purpose of private encapsulation and to reduce namespace clutter. Similarly, extern should be avoided, as it leads to bad design and spaghetti programming.

C++: static vars not persisting between files

I have a config.h file with a bunch of constants.
in main.cpp, it sets one of the constants to some value, and then calls a function in util.cpp.
util.cpp also has config.h included, but the variable set by main.cpp does not have the same value.
Code:
config.h:
static int MAX_NUMBER_OF_TRAINING_DATA = 1000;
main.cpp (main):
else if (strcmp(argv[i], "-mTrnData") == 0)
{
MAX_NUMBER_OF_TRAINING_DATA = atoi(argv[i + 1]);
cout << "Number of data sets to be generated: " << MAX_NUMBER_OF_TRAINING_DATA << "\n\n";
// prints what I tell it
}
and in utils.cpp
cout << "Number of data sets generated: " << MAX_NUMBER_OF_TRAINING_DATA << "\n\n";
// prints the default value (in this case, 1000)
So, how do I fix this so that I can have my config.h file of constants be remembered throughout my cpp files?
In Java, you can do Config.NAME_OF_CONSTANT , so, if there is a way to do that in C++, that would be most grand.
I know constants aren't supposed to change, but the only time they do change is in main() when reading in the arguments from the running the program... after that they don't change.
Each translation unit receives its own copy of static data.
The easiest way to verify this is to print the address of MAX_NUMBER_OF_TRAINING_DATA in both units - it will be different. To avoid it, declare it extern in the header and define it once in one unit, for example in main.cpp.
Apart from that is it evil to have such global variables (whose naming scheme even suggests that we're talking about constants!). You might consider to refactor the code, for example use a getter GetMaxNumberOfTrainingData() to make the value available while keeping write access to it restricted to a single unit.
A non-const static variable at namespace scope in a header file is
almost certainly an error. You get an instance of the variable for each
file that includes the file. If you want to use the same variable in
several different translation units, declare it extern (and without
the initializer) in the header, and then define it (without the
extern, although you can also use the extern if there is an
initializer) in a single source file.
A static variable has a "file scope" by definition. So by declaring it in a header file, every .c file that includes it gets its own variable. They have nothing to do with each other.
You should genereally never declare variables in header files. If you need a variable in multiple modules, declare it in one file and add them as extern in all other files you need it.
From a design point of view, you should switch to a Configuration or Option object.
Each class would depend on an instance of this object to be provided, and you could have different initializations routines: from a file, from command line, etc...
Better yet, you would avoid the global variables!

C++ accessing variables from .CPP files

I'm a little fuzzy on how variable access between .cpp files works. For instance:
main.cpp
int main()
{
int a = i;
return 0;
}
main2.cpp
int i;
This generates a compiler error on main.cpp, telling me there is no in i in existence. What difference then, does the "static" keyword do in this context? (I tried Googling for it, but most of the "static keyword" info pages talk about classes & functions)
main2.cpp
static int i;
Is it the same? Does it prevent extern int i being used to access i elsewhere? How does the use of anonymous namespaces differ in how variables are handled?
main2.cpp
namespace
{
int i;
}
To sum up:
Can variables be accessed between .cpp files? (aside from extern keyword)
How does the static keyword on a global variable affect things?
How do anonymous namespaces affect things differently?
In your first example, main2.cpp defines a global variable i, which could have been accessed by main.cpp if an extern declaration of i had appeared in that file. (Normally that extern declaration would come from a header file.) You got a compiler error because i had never been declared in main.cpp, which means the compiler assumes there is no such variable.
In your second example, main2.cpp defines a file scope variable i. File scope variables are distinct from globals, even if they happen to have the same name. If you had had an extern declaration of i in main.cpp in the second example, both files would have compiled successfully, but then you would have gotten a link error because no global variable i was defined.
If you renamed main2.cpp from the second example to main3.cpp, added an extern declaration of i to main.cpp, compiled all three and linked them all together, that would succeed; main.cpp and main2.cpp would share one variable named i, and main3.cpp would have its own entirely separate variable also named i.
This stuff is called linkage. Namespaces are almost entirely unrelated to linkage. However, the anonymous namespace is special. Defining a variable in an anonymous namespace is for all practical purposes the same as defining it with static -- it makes it a file scope variable. (If I remember correctly, there is a difference, but it only matters if you are doing complicated things with exported templates, and as exported templates are so little used that they're talking about deleting the feature from the C++ standard, you don't have to worry about it.)
The value of the anonymous namespace is that you can put a class definition inside it, and that makes all of the class's methods be file-local. (Only the class { ... } block has to be inside the namespace { ... } block to get this effect.) You can't do that any other way.
All global variables have some kind of linkage. extern linkage is required to name the same variable in different contexts between different files.
extern is the default. If you actually use extern in a variable declaration, it's treated as a reference to another file. Omit any linkage specifier to actually create the variable; this must happen in only one file.
extern int i; // i exists somewhere in some .cpp file.
int i; // ah! this is the file it exists in.
// (Although nothing special about that.)
static applied to a global (at namespace scope) makes it local to the file. You get the same effect from a private namespace, so static outside function or class scope is deprecated. Many still use it though.
The exception to the rule of static meaning file-local is in classes and inline functions. Class static members should more properly be called extern since the semantics are identical. It's ugly and confusing, but I guess Bjarne just wanted to eliminate extern as a keyword.
Inline functions can have the same definition among multiple .cpp files, so when one creates a static variable, the variable definition is shared as well.
yes, for example you can use static class variables
it makes variable local and persistent to compilation unit
anonymous namespace prevents collision between symbols. it is as if you create uniquely named namespace manually

Static variables in C++

I would like to know what is the difference between static variables in a header file vs declared in a class. When static variable is declared in a header file is its scope limited to .h file or across all units. Also generally static variable is initialized in .cpp file when declared in a class right? So that does mean static variable scope is limited to 2 compilation units?
Excuse me when I answer your questions out-of-order, it makes it easier to understand this way.
When static variable is declared in a header file is its scope limited to .h file or across all units.
There is no such thing as a "header file scope". The header file gets included into source files. The translation unit is the source file including the text from the header files. Whatever you write in a header file gets copied into each including source file.
As such, a static variable declared in a header file is like a static variable in each individual source file.
Since declaring a variable static this way means internal linkage, every translation unit #includeing your header file gets its own, individual variable (which is not visible outside your translation unit). This is usually not what you want.
I would like to know what is the difference between static variables in a header file vs declared in a class.
In a class declaration, static means that all instances of the class share this member variable; i.e., you might have hundreds of objects of this type, but whenever one of these objects refers to the static (or "class") variable, it's the same value for all objects. You could think of it as a "class global".
Also generally static variable is initialized in .cpp file when declared in a class right ?
Yes, one (and only one) translation unit must initialize the class variable.
So that does mean static variable scope is limited to 2 compilation units ?
As I said:
A header is not a compilation unit,
static means completely different things depending on context.
Global static limits scope to the translation unit. Class static means global to all instances.
PS: Check the last paragraph of Chubsdad's answer, about how you shouldn't use static in C++ for indicating internal linkage, but anonymous namespaces. (Because he's right. ;-) )
Static variable in a header file:
say 'common.h' has
static int zzz;
This variable 'zzz' has internal linkage (This same variable can not be accessed in other translation units). Each translation unit which includes 'common.h' has it's own unique object of name 'zzz'.
Static variable in a class:
Static variable in a class is not a part of the subobject of the class. There is only one copy of a static data member shared by all the objects of the class.
$9.4.2/6 - "Static data members of a
class in namespace scope have external
linkage (3.5).A local class shall not
have static data members."
So let's say 'myclass.h' has
struct myclass{
static int zzz; // this is only a declaration
};
and myclass.cpp has
#include "myclass.h"
int myclass::zzz = 0 // this is a definition,
// should be done once and only once
and "hisclass.cpp" has
#include "myclass.h"
void f(){myclass::zzz = 2;} // myclass::zzz is always the same in any
// translation unit
and "ourclass.cpp" has
#include "myclass.h"
void g(){myclass::zzz = 2;} // myclass::zzz is always the same in any
// translation unit
So, class static members are not limited to only 2 translation units. They need to be defined only once in any one of the translation units.
Note: usage of 'static' to declare
file scope variable is deprecated and
unnamed namespace is a superior
alternate
A static variable declared in a header file outside of the class would be file-scoped in every .c file which includes the header. That means separate copy of a variable with same name is accessible in each of the .c files where you include the header file.
A static class variable on the other hand is class-scoped and the same static variable is available to every compilation unit that includes the header containing the class with static variable.