do statics need a class? - c++

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.

Related

"Private" variable in namespace scope in cpp file

In a source file (not a header file), I have the habit of placing some state that only the implementation can work with:
//.cpp
namespace foo{
someType bar;
//... functions and objects that might use bar ...
}
Because bar is declared only in this cpp file, it is not possible for other code files to use it, correct?
Note, however, I have not placed static before it. In this case, though, that should make no difference?
Without static, is the only difference that this variable could be accessed (and actually set) by another code file if in some other file -- either header or cpp -- I had an extern declaration for the same variable name? (and of course, that this declaration was within a namespace of the same name)
Since I do not have any such extern declaration anywhere else in the code base, I gather that it makes no difference whether I mark this as static or not -- but I wanted to make sure that my thinking is correct.
You are correct, static on variables in namespace scope controls only the visibility of the variable from other translation units (internal vs. external linkage). Apart from that, the behavior of the variable is going to remain the same. For example, it storage class would remain static. The only difference is that without static a declaration
namespace foo{
extern someType bar;
...
}
from some other translation unit is going to "connect" to your bar variable, while with static the extern would fail at linking time.

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.

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

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.

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.