I got a little confused of the usage of static / global / global static / extern variables.
I would like a counter variable to get increased in any creation of a class instance.
Would highly appreciate if someone can post a clarification of the appropriate usage for each.
According to OO concept, you should NEVER use global static variables.
You can instead define a static variable in your class for the instance count of your class.
Make it private, so that no one else except your constructor can increase the count.
Provide a public function to get the counter. See example below:
yourclass.h:
class YourClass {
private:
static int instanceCount_;
public:
YourClass() {++YourClass::instanceCount_;} // constructor
~YourClass() {--YourClass::instanceCount_;} // destructor
static int instanceCount() {return instanceCount_;}
};
yourclass.cpp:
int YourClass::instanceCount_ = 0;
As far as the concept of static / global / global static / extern
static:
1a) global static:
A static variable created as given: static int numberOfPersons;
This kind of variable can only be seen in a file (will not have name collision with other variable having same name in other files)
1b) class static: (already has an example in the instance count above)
A class may have static members, which are visible to that class (accessed only by Class::VarName syntax) only (instead of 'file only' as said above). It will not have name collision with variables of same name in other class. It only has one copy per class (not per instance).
1c) Both global static and class static are global(since they can be globally accessed, either with class qualifier Class:: or not.
So, 1a., 1b. and 1c. partially explain static, global, and global static
Another form of global variable, is just define a variable without static
syntax: int numberOfPersons;
Without static, this variable can be seen by other file, using extern keyword. And it will have name collision with the variables having same name in other files. So, globally, you can only define it ONCE across all your source files.
extern: Declare a variable/function which is defined in somewhere else. It is normally seen in a header file. We can have some variables defined in other file, and declare this variable as extern, like below, in another source file which uses it.
extern int numberOfPersons;
int addPersonCount()
{
numberOfPersons++;
}
Hope this helps.
Related
I am working with a class whose constructor declares and initializes a static const variable in the implementation. This is not a data member of the class. I understand the use of const in this context, but what is gained by using static?
I understand that the static const global constants are shared by all instances of the class. Does that also happen with the variable inside the constructor?
Also, why would this not be defined at the Global scope, like the other two? That's where I would normally define my constants.
Example Code:
#includes...
static const int GLOBAL_CONST1 = 100;
static const double GLOBAL_CONST2 = 1.0;
SomeClass::SomeClass()
:
theDataMember1 (),
theDataMember2 (),
...
{
static const double SOME_VAR = 0.01; // Why not declare this globally?
theDataMember1 = SomeIncludedClass(SOME_VAR);
}
Static Variable gets constructed only once no matter how many times the function is called.
So in case your defining constants inside a function and the function is called multiple times, then to reduce the cost of constructing this object every time the function is called you would make it a static variable (Mainly useful when its a constant, Else you may end up changing this value and it soon gets messed up).
For your second question, This is because you don't want others to be able to access the value of variable "SOME_VAR". Giving a global scope means any one can access it.
This link provides a good example about how local static is sometimes useful than global static variables.
When the constant is used only in one single function it can make sense to declare it only in the scope of the function it is used in. Why the static is used here does not really make sense to me, because it will be the same in all instances of the class anyway since it is a compile time constant.
But:
You can also initialize the constant from parameters computed at runtime. In that case the value of the constant will be defined by the first instance of the class:
class A {
public:
A(int param)
{
static const int MY_CONST = param;
cerr << "param: " << param << " const: " << MY_CONST << endl;
};
};
int main()
{
A a1(1);
A a2(2);
return 0;
}
output:
param: 1 const: 1
param: 2 const: 1
// Why not declare this globally?
By only seeing an abridged code fragment, we can only guess. It's typically good practice to put your variables in the narrowest scope possible. After all, everything could be global - we just choose to encapsulate things.
Perhaps the global constants are actually used in a lot of places, whereas the local constant is only used in that local function.
but what is gained by using static?
Probably just consistency. If you're just used to typing your constant values like:
static const T val = ddd;
everywhere, why change when you do it locally? There isn't an advantage or disadvantage of static for creating constant numbers.
static variables are literally static: they are allocated in same place as global variables. Plain local variables are allocated every time function is called on stack. If function is called n times recursively, there are n local variables. Static variable initialized only once. After it has been initialized, there is be only one instance of static variable. So static const local variable is used because of performance reasons.
Variables should have as narrow scope as possible to avoid unnecessary coupling. That's why this variable is local.
This looks like an attempt at premature optimization. Allegedly someone who created the code believed that by using static double variable they will save on creating the variable every time the function is entered.
However, since compilers are not morons, in practice it doesn't matter at all. Optimizing compilers will replace the variable with access to pre-allocated and initialized memory regardless, static or no static.
According to the OP's Code:
#includes...
static const int GLOBAL_CONST1 = 100;
static const double GLOBAL_CONST2 = 1.0;
SomeClass::SomeClass()
:
theDataMember1 (),
theDataMember2 (),
...
{
static const double SOME_VAR = 0.01; // Why not declare this globally?
theDataMember1 = SomeIncludedClass(SOME_VAR);
}
One has to take into consideration a few things:
Data Storage Unit - Storage Class Specifier
Data Storage Duration - Minimum Life Of Data
Scope Visibility - Where The Data Unit Is Visible.
Here is an excerpt:
Global objects and objects in a namespace scope, static data members of a class, and local static objects in functions reside static storage duration. An object with static storage duration resides in the same memory address throughout the program's execution. Every such object is constructed only once during the lifetime of the program. By default, static data is initialized to binary zeros. Static objects with a nontrivial constructor or an explicit dynamic initializer undergo a second initialization phase called dynamic initialization.
The scope of an object declared static in a function is restricted to that function. Objects with static storage duration appear in the following examples:
int num=0; //global variables have static storage
extern int x; //also global, defined in a separate translation unit
int func()
{
static int calls; //local static. initialized to 0 by default
x=calls;
return ++calls;
}
class C
{
private:
static bool b;
};
namespace NS
{
std::string str; //str has static storage
}
The extern Storage Class Specifier
The extern specifier can be applied only to the names of objects and to functions. The extern specifier cannot be used in the declaration of class members or function parameters. Identifiers declared extern have external linkage, meaning they are visible from all translation units of the same program.
A name declared in a namespace scope without a storage-class-specifier has external linkage unless it has internal linkage because of a previous declaration and provided it is not declared const. Objects declared const and not explicitly declared extern have internal linkage, meaning they are visible only from the translation unit in which they are declared.
Notice that the extern keyword is overloaded. It can also be used in explicit-instantiations of templates and in and linkage-specifications, but it is not a storage-class-specifier in such contexts.
The thread_local Storage Duration
The thread_local specifier indicates that the named object or reference has thread storage duration. thread_local shall be applied only to the names of objects or references of namespace scope and to the names of objects or references of block scope that also specify static as their storage class. The thread_local storage class is a new C++09 feature. It's discussed in detail here.
that can be found at this site: C++ Reference Guide | Static Storage Duration
The OP had stated and asked this:
I am working with a class whose constructor declares and initializes a static const variable in the implementation. This is not a data member of the class. I understand the use of const in this context, but what is gained by using static?
I understand that the static const global constants are shared by all instances of the class. Does that also happen with the variable inside the constructor?
Also, why would this not be defined at the Global scope, like the other two? That's where I would normally define my constants.
To answer his/her questions based on the excerpt above and from my own intuition:
their first question:
"What is gained by using static?" static data storage units have automatic initialization. They are created only once and reside in that same memory address or allocation unit.
their second question:
"Does that also happen with the variable inside the constructor?" Yes & No - Yes there is a single instance of this variable upon construction and initialization in the static storage memory unit, but no this is not visible to every instance of the class; it is only local to the Constructor of this class because of scope visibility.
their final question:
"Also, why would this not be defined at the Global scope, like the other two?" This particular variable depending on intention of use might only be used in the initialization of another object. One of the benefits of this maybe to not having to use a stack variable, and is only visible to this class' constructor. So when this constructor is called ctor this static const variable is created and initialize only once per construction and once this class object's constructor goes out of scope this static const variable is no longer visible by any other function or member of this class, or any other translation unit that is outside the visibility of this scope.
There is no definitive answer, however I tried to provide as much insight as I can in regards to the OPs questions, and tried to answer them to the best of my abilities. Some of the things that can vary are the intentions of the programmer and the context in which these memory allocations units are, declared, defined, initialized and then used.
struct A
{
static void f();
};
static void A::f() {} //illegal
Why's this not allowed? Am asking this because the rule seems inconsistent with other keywords.
You must put constexpr on both.
You can put inline on both, but you can also omit one of them. This is useful that you can omit inline in class definition, which is not important information of the interface.
But the rules for static on class members doesn't really make sense. Shouldn't it be consistent with constexpr?
I know static means internal linkage for namespace-scope functions, and this partly explains the current shape. But isn't distinguishing between free functions and class member functions having no ambiguity in namespace scope? For example, if you write static void A::f() {} it's unambiguous that you're defining a member function of A, if A is a class name.
The static in class have other meaning the static in a global or namespace.
when you declared symbol as static in the class, you don't want it to be a global static.
1. static member
In the class it is mean the symbol is class related not object related, means for member variable, there is only one instance for all the objects, and for function, it doesn't have access to non static members, which are object oriented. .
2. static global
In global scope, the static indicate the object or function is local only, and can't be exported (like using extern) to other files. in addition it let you use same name in other file for other variable. so if it located in header file, any file including the header, will have different instance of the symbol.
Therefore if you were allowed to use it in the global scope for a member, then there was an ambiguity.
I have class with static string variable m.
class turbo
{
public:
static string m;
}
if I not declare like defined below I will get error undefined reference turbo::m.
string turbo::m;
Why I should declare it twice? I don't need to declare non static variables second time. Where is logic?
To be honest, I was surprised by this too the first time,
but found the very reasonable reason for it.
while member variables are stored within the object allocated space,
static members are not placed within the object memory space (either heap or stack)
but have a private shared space. just like functions do.
Therefore, declaring the static string m within the class.
is just like saying: there is a shared definition of this somewhere
and the name is turbo::m.
Hope this clears things up.
It's the difference between declaration and definition, very much like declaring a function with a forward reference, e.g.;
int MyFuncion();
and actually defining it with its function body, e.g.,
int MyFunction()
{
return 1;
}
I know you have an object and not a function, but conceptually, the declaration/definition idea is the same.
C++ forbids the definition of non-const static data members in the body of a class ("inline definition"). It becomes more obvious if you try to use an explicit constructor: for example,
class turbo
{
public:
static string m;
static string s = string("my_str"); // doesn't work
}
Hence, when you write static string m in the body of a class, it is merely a declaration, not a definition. You will have to define it later:
static string turbo::s = string("my_str");
In your case, you are simply invoking the default constructor in the definition:
static string turbo::m; // calls the default constructor
(Like any static variable, initialization occurs at the very start of your program, before main.)
Note that the definition must also occur only once (to avoid multiple definitions), so it must not appear in a header file.
In the class definition you only declare the static variable
class turbo
{
public:
static string m;
}
but it is not yet defined. To define the corresponding object you have to write
string turbo::m;
Now it will exist regardless of whether instances of the class were created.
Can anyone please tell me when the static variables/functions are allocated memory and in which memory segment? i.e. static global variable, static member variable, static local variable etc all are initialized once before the beginning of program and all retains its values?
Furthermore, If Class MyClass has static variable count, when I declare MyClass obj in main, then MyClass object is created and count is given memory, If I declared MyClass obj2, what happens in terms of memory? Is there any count in obj2 which refers to the count of obj1? Or there is only separate memory allocation. Hope so that I am able to clearly ask the question.
Thanks in advance.
When we declare a member of a class as static it means no matter how many objects of the class are created, there is only one copy of the static member. It exists even though no objects of the static data member's class exist.
A static member is shared by all objects of the class.
If I declared MyClass obj2, what happens in terms of memory? Is there any count in obj2 which refers to the count of obj1?
Yes. There is only one count for all objects. This test program would explain this a bit clear;
class Something
{
public:
static int s_nValue;
};
int Something::s_nValue = 1;
int main()
{
Something cFirst;
cFirst.s_nValue = 2;
Something cSecond;
std::cout << cSecond.s_nValue;
return 0;
}
output:
2
Because s_nValue is a static member variable, s_nValue is shared between all objects of the class. Consequently, cFirst.s_nValue is the same as cSecond.s_nValue.
Furthermore, If Class MyClass has tatic variable count, when I declare MyClass obj in main, then MyClass object is created and count is given memory
No. In fact, count exists even if there are no objects of the class have been instantiated!
The keyword static can probably be seen as somewhat "overloaded".
The following usage-options are all viable:
Static local variables
Static global variables
Static member variables
Static global functions
Static member functions
Variables:
In terms of runtime, all types of static variables are essentially the same. They all reside in the data-section of the program, and their addresses remain constant throughout the execution of the program. So the only difference between them is during compilation, in the scope of declaration:
Static local variable: recognized by the compiler only in the scope of the function
Static global variable: recognized by the compiler only in the scope of the file
Static member variable: recognized by the compiler only in the scope of the class
Functions:
In terms of runtime, all types of functions (static and non-static) are essentially the same. They all reside in the code-section of the program, and their addresses remain constant throughout the execution of the program. So the only difference between them is during compilation, in the scope of declaration:
Static global function: recognized by the compiler only in the scope of the file
Static member function: recognized by the compiler only in the scope of the class
The keyword static has different meaning depending on the context it is used in. static variables are allocated on the heap and their lifetime extends across the entire run of the program.
A static global variable is same as a global variable except that the static keyword limits the scope of the variable to the file containing it only. This is called file linkage or internal linkage.
A static member variable is created when the class containing it is defined. This means it can be accessed using the class's name. This variable is shared across all instances of the class.
A static local variable has the same lifetime as that of a static global variable except that its scope is the immediate block containing it.
When a function is qualified with the static keyword, this means that the scope of the function is the file containing it only. The function cannot be called by a function in another file. This is, again, called file scope or internal linkage.
What if I declare a class variable as extern so that it can access some global variable declared in some other file? Does such a scenario come up anytime or is it just a hypothetical case?
Lets say I have a header file global.h
extern int myglobalint;
and I have a cpp file my.cpp
Here I declare a class A
class A{
//use that variable here....is it possible
}
Yes it comes up from time to time, particularly in messy code. :D
Perhaps a more C++-like style would be to keep these kinds of variables together in a class, eg in global.h:
class Global { // You can do this with 'struct' & omit 'public'
public:
static int myglobalint;
};
And in global.cpp:
int Global::myglobalint = 0xbeef;
There's really no advantage doing it with an extern or class members - but unless it's some kind of global setting or flag, if you're resorting to storing state globally you probably need to put some thought into your design.
If you really do need global variables, for example, state or configuration that really has no other place to live, I would choose the class-static approach over a mess of extern's.