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.
Related
I've actually never tried it until now.
Is it possible to have statics just in namespace scope without a class?
Why not?
namespace MyNamespace
{
static int a;
}
assign something, somewhere else....
Annex D (Compatibility features) [C++03]
D2: The use of the static keyword is deprecated when declaring objects in namespace scope.
static variable at namespace scope (global or otherwise) has internal linkage. That means, it cannot be accessed from other translation units. It is internal to the translation unit in which it is declared.
update
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.
Take for example:
// myheader.h
static int myStaticVar = 0;
// If we remove 'static' the compiler will throw linker error.
void DoStuff();
// and myheader.cpp, and main.cpp; etc
This is how I would explain it:
Static variables do not have external linkage, and when we compile
without 'static' we are "including" the static variable (which is
global here) in every file, which create duplicates and linker will
throw an error since multiple declaration is not allowed.
Is there any better way to explain this? Thanks.
PS: Are we suppose to have static variables (not talking about members) in header file?
Why can't a non-static variable reside in a header file?
Because it breaks the One Definition Rule(ODR).
When you include the header file containing a non-static variable, the declaration of the variable gets pasted in each source file where it is included. Thus you end up having more than one definition of a variable in same Translation Unit, this violates the ODR and hence the linker will give you linking errors.
How to explain static variables declared in header files?
When you declare a static variable in an header file, an copy of the variable gets created in each Translation Unit where the header file is included.
Declaring a static variable in header file will not give you multiple definition erros but it does not acheive your purpose of having a global variable whose value is shared accross all files which access it.
You may think that since you are using a global static variable its value will be retained accross different files, but as mentioned above each Translation Unit has its own copy of the variable and it does not acheive what you think you are acheiving.
Are we suppose to have static variables (not talking about members) in header file?
No,Never!
How do you declare and define global variables?
You need to use extern keyword.
Add the extern declaration of the variable in an header file. The header should be included by the one source file that defines the variable and by all the source files that reference the variable. Only one source file should define the variable. Also only one header file should declare the variable.
filename.h
extern int gVariable; /* Declaration */
file1.cpp
#include "filename.h"
/* Definition */
int gVariable = 37;
void doSomething(void)
{
return gVariable++;
}
file2.cpp
#include "filename.h"
#include <stdio.h>
void doSomethingWithGlobal(void)
{
printf("Global variable: %d\n", gVariable++);
}
First, read this answer to a similar question.
To complement the answer based on your question, here goes:
When you #include a file (any file, .h files is a common convention), it almost basically just copy-pastes it in your code. If you have non-static variable in the header file and you include it in two source files, the variable gets copy-pasted in both source files and well you get a link error as I explained in the answer I told you to read above.
If you want to share a global variable across many source files, you should do this:
In only one of your source files:
type global_var = default_value;
In the header file:
extern type global_var;
So, this way, all the source files see there is going to be a global_var somewhere in the bunch of source files. Only one of the source files actually contains that variable and when linking happens, all the source files would be referring to that one instance of global_var
The header file (.h) tells you (declares) what the definition file (.cpp) will do.
For a metaphor - a header file is like to telling a lot of friends that you are going to do something, but in reality you are going to do it once.
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.
class X {
static int i;
// some other function, variable declaration, cons, dest
};
int X :: i ; **(!)**
Why must I write that (!) line, always ?
If I dont write, compiler cannot complete internal linkage, and so it gives ( I assume ) linker error. Why ?
This is known as the One Definition Rule. Each global object (technically, each object with external linkage) must be defined in exactly one source file (technically, in one translation unit). However, it can be declared as many times as you like.
Typically, a class definition will be in a header file, which might be included by many source files. So any static members can't be defined there, only declared, otherwise there will be multiple definitions. You must separately define the static members in exactly one source file, in order for the linker to find exactly one definition. That is what the line marked (!) does.
Because that is how static members work. They exist apart from the instances directly in the class.
You can't define them inside the class, because then you would have multiple definitions for every implementation file that is using your class.
Therefore you need to choose one implementation file that will actually define the static member.
The static variable must be defined (as opposed to declared) in a TU (i.e. a cpp file).
If it's only declared and not defined, no storage is allocated for it, so the linker can't find it.
static int i; is a declaration, i.e. tells to the compiler that in some translation unit (=>.cpp file) such static field will be actually defined. It is needed to let the compiler know that such variable exists and to let you use it in each translation unit where it's declared.
int X :: i;, instead, is a definition, it tells to the compiler to actually provide the space for that variable. It must stay in a single .cpp, otherwise each translation unit would provide some space for it on its own (and the linker would complain).
It's the exact same reason why for globals you need an extern declaration in every file that needs to use it (usually put in a header) and a normal definition in the single .cpp that defines it.
C++ makes a clear distinction between declaration and definition. You need to tell the compiler two things:
The data type of the variable: declaration.
The place in memory on where you want your variable to be located: definition.
This is usually done in one single step, ie a local int variable:
void f() {
int x; // Declaration and definition.
}
Since a .hpp header file can be included on many .cpp files, your (!) line must reside on a single specific .cpp, usually outside any header file.
Static class members are shared among all class instances (there is one and only place in memory where such variable resides) and therefore static int i; inside class declaration represents variable declaration only - and you need to allocate memory for that variable somewhere - you need to define it - which is done in implementation file with int X::i;
The class definition only defines the member, but it must exist in a single compilation unit (i.e. a .cpp file).
You could say it is part of the "one-definition rule".
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.