c++: Static variable defined in constructor - c++

I'm curious about what is really happening "under the hood" here. I'm creating a Class with an ID variable automatically assigned when the constructor is called, depending on how many instances have been created in the past.
Class:
class MyClass{
int ID;
public:
MyClass(){
static int id{1}; // Seems to be redefined every time the constructor is called.
ID = id++;
}
};
Main:
int main()
{
MyClass a; // ID = 1
MyClass b; // ID = 2
MyClass c; // ID = 3
return 0;
}
I'm only used to use static member variables that are initialized in the global scope (i.e. MyClass::staticVariable = 1), so this "in-class" initialization confuses me, as what is really happening.
Is the static variable defined only the first time the line is run, and then ignored? Is this the general behaviour for any function AND member function?

For all intents and purposes the behavior is the same as static member variables that are initialized at global scope, which you seem to grasp. The only difference I can see between the two is the scope, the static variable declared in the constructor is only avalilable at constructor scope, whereas a static variable declared as class member is, of course, avalilable at class scope, following the access rules, as all the ohters.

id is a static local variable. Using the static keyword on a local
variable changes its duration from automatic duration to static
duration.
According to cpp ref, the initialization is done the first time control passes through their declaration. On all further calls, the declaration is skipped.
Static local variables and lifetime-of-a-static-variable are some interesting detailed articles.

Related

Why static global variables initialized to zero, but static member variable in class not initialized?

static int counter // will initalized to 0
but if I make that variable inside a class, it's not initialized and I have to initialize it outside of class
class Test {
static int counter; // not initialized
};
...
Test::counter = 0;
I know the static variables are stored in BSS segment in memory and initialized by default to 0, so why is it when I make a static in class not initialized?
Why static global variables initialized to zero, but static member variable in class not initialized?
Because the declaration for a non-inline static data member inside the class is not a definition.
This can be seen from static data member documentation:
The static keyword is only used with the declaration of a static member, inside the class definition, but not with the definition of that static member. The declaration inside the class body is not a definition and may declare the member to be of incomplete type (other than void), including the type in which the member is declared:
Also the out of class definition Test::counter = 0; is incorrect. It should instead be int Test::counter = 0;
The question is based on a false premise. Static member variables are subject to zero initialization. The following code would perform the expected zero initialization of counter.
class Test {
static int counter; // declaration, not defined yet
};
int Test::counter; // definition with zero-initialization
It's not the initialization that is required, but the definition. Without the definition, the compiler has no place in which to perform the initialization, zero or otherwise.
See also Undefined reference to a static member and Defining static members in C++ for more background information.

Static variable vs static member

I saw this at work, and it is written by people before I joined. A static variable is used instead of static member of the class. As for now, I don't see a reason why static member of the class should not be used here. If I want to persuade people here to change it, is there any good excuse to convince them?
I tried to find the difference between static member and static variable, seems like people are leaning toward static member shall always be used unless there is a good reason, but not very real life cases were mentioned.
Current code:
class Foo {
public:
static Foo *get() {
static Foo _instance;
return &_instance;
}
// ...
};
How this function is being used:
int XXX_loadxxx(const char xxx, foo_handle *handle) {
// just get foo ptr and return
xxx::foo *ptr = xxx::foo::get();
int ret = ptr->init();
if (ret != 0) {
return -1;
}
*handle = ptr;
return 0;
}
Code in my mind how the class should be defined:
class Foo {
static Foo _instance;
public:
static Foo *get() {
return &_instance;
}
// ...
};
I'd really appreciate if someone can tell me whether it makes any different to change it to static member, and why.
The first solution is better for two reasons:
the static singleton is initialized the first time get() is called, which means you have a predictable behavior, which is not the case with static variables on different translation units
the variable is local so it's only visible from the getter of the singleton, which is usually what you want
I don't see why you would prefer to de-encapsulate it from the method.
Both samples cannot be compiled. What does the static Foo_instance mean? Did you mean static Foo instance?
Now back to your question: if you define the static variable inside of a function, it will be initialized only when you call the function for the first time. That has 2 consequences:
You will not spend resources if you never use this object;
If the constructor requires other resources to be allocated, you may need to control the time of creation. The time of creation of the static member is not defined.
The static member variable (as well as static variables in namespace scope) has a few disadvantages compared to a static local variable:
It must be defined in a single translation unit. This is not an option for libraries that desire to be "header only". This limitation no longer exists in C++17, which introduced inline variables.
The order of initialisation of static objects defined in different translation units is undefined. This often leads to undefined behaviour when static objects depend on other static objects, and may get initialised in the wrong order. This problem is called "Static Initialization Order Fiasco". The function local static (mostly1) solves this problem, since it is instead initialised on first use. As such, this idiom is called "Construct On First Use".
1 There is still a convoluted way of violating the ordering guarantees even with Construction On First Use: If there is static object A, whose constructor does not depend on static object B, but the destructor of A does depend on B, then B may still be destroyed first resulting in UB. This can be avoided by always calling the static getter of B in the constructor of A if any part of the A depends on B. In general, static objects should be avoided because of these problems.
P.S. Typically, you'd want to return a reference from the getter, so that the caller doesn't need to worry about getting null.
P.P.S. static Foo_instance; should probably be static Foo instance;
P.P.P.S. With the static member, the getter becomes mostly2 useless; the member could instead be made public.
2 It may still have some value if you intend to use inheritance, to extend the static object while maintaining compatibility with the original interface.
The local static varaible initialization is safe in a concurrent environment.
Another advantage is that it is initialized onlt in the case when the corresponding function is called. That is the variable is innitialized by a request.
From the C++ 17 Standard
4 Dynamic initialization of a block-scope variable with static storage
duration (6.6.4.1) or thread storage duration (6.6.4.2) is performed
the first time control passes through its declaration; such a variable
is considered initialized upon the completion of its initialization.
If the initialization exits by throwing an exception, the
initialization is not complete, so it will be tried again the next
time control enters the declaration. If control enters the
declaration concurrently while the variable is being initialized, the
concurrent execution shall wait for completion of the
initialization. If control re-enters the declaration recursively
while the variable is being initialized, the behavior is undefined

In C++, what is the benefit of defining a Static Const variable within a member function?

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.

Initialization of static class variable inside the main

I have a static variable in the class.
I am Initializing that in the global scope, its works fine.
But
When I try to Initialize in the main linker throws an error.
Why it so.
class Myclass{
static int iCount;
} ;
int main(){
int Myclass::iCount=1;
}
And In global scope why I have to specify the variable type
like
int Myclass::iCount=1;
As In my class I am definig iCount as integer type why not.
Myclass::iCount =1 ; in //Global scope
The section $9.4.2/7 from the C++ Standard says,
Static data members are initialized
and destroyed exactly like non-local
objects (3.6.2, 3.6.3).
Note the phrases "initialized" and "exactly like non-local objects". Hope that explains why you cannot do that.
In fact, static members are more like global objects accessed through Myclass::iCount. So, you've to initialize them at global scope (the same scope at which class is defined), like this:
class Myclass{
static int iCount;
} ;
int Myclass::iCount=1;
int main(){
/*** use Myclass::iCount here ****/
}
Similar topic:
How do static member variables affect object size?
Because C++ syntax doesn't allow this. You need to instantiate your static variable outside of the scope of some function.
Besides you forget a semicolon ; after your class ending bracket.
this is the correct C++. Outside of a function, in a cpp file. the initialisation is done at the beginning/launching of the executable. ( even before calling main() );
//main.h
class Myclass{
static int iCount;
}; // and don't forget this ";" after a class declaration
//main.cpp
int Myclass::iCount=1;
int main(){
}
From C++ standard (§8.5/10):
An initializer for a static member is in the scope of the member’s class.
class Myclass has global scope and you tried to initialize its static member in the narrower scope - of the function main.
The static initialisation occurs before main is called by the run-time initialisation.
Placing it within a function is not allowed because that is where locally scoped objects are declared. It would be confusing and ambiguous to allow that.

What exactly does "static" mean when declaring "global" variables in C++?

This is an expansion of the scope of a previous question of mine.
What exactly is "static", how is it used, and what is the purpose of using "static" when dealing with C++?
Thanks.
It means that the variable is local to a translation unit (simply put, to a single source file), and cannot be accessed from outside it. This use of static is in fact deprecated in the current C++ Standard - instead you are supposed to use anonymous namespaces:
static int x = 0;
should be:
namespace {
int x = 0;
}
The keyword static has different meanings in C++, depending on the context.
When declaring a free function or a global variable it means that the function is not to be available outside of this single translation unit:
// test.cpp
static int a = 1;
static void foo() {}
If the result of compiling that translation unit is linked with a different translation unit containing symbols a and foo it will not break the One Definition Rule, as in this particular translation unit a and foo are private symbols. This use has been obsoleted by unnamed namespaces.
// test2.cpp
namespace {
static int a = 1;
static void foo() {}
}
When declaring a local variable within a function it means that the lifetime of the variable will extend from the first call to the function to the end of the program, and not only for the duration of the call:
int foo() {
static int counter = 0;
return ++counter;
}
int main() {
for ( int i = 0; i < 10; ++i ) {
std::cout << foo() << std::endl;
}
}
In the previous code, counter is initialized once when foo is called for the first time, but the variable will outlive the function and keep the value across different function calls. The previous code will print "1 2 3 4... 10". If the variable was not declared static then the output would be "1 1 1... 1".
Within a class scope, static means that the member is a member of the class, and not of a particular instance. This use is equivalent to the use in your other question: usage of that particular member is not bound to any specific object.
struct test {
int x;
static int y;
};
int test::y; // need to define it in one translation unit
int main() {
// test::x = 5; // !error cannot access a non-static member variable
// without an instance
test::y = 5; // ok
test t, other;
t.x = 10; // ok
t.y = 15; // ok, the standard allows calling a static member through
// an instance, but this is the same as test::y
}
In this case, the member x is a non-static member attribute, and as such there is a different x for each instance of the class. In the sample program t.x and other.x refer to different integers. On the other hand y is static and thus there is a single instance of test::y in the program. Even if the standard allows to call t.y and other.y both uses refer to the same variable. The same goes with member methods. If they are static they are class-level methods and can be called without an instance, while if they are non-static they are applied to a concrete instance and the a.b or a->b syntax must be used.
This use of static is similar to the use of the same keyword in Java, while the other two are not present in that language. There is one use of the keyword in Java that is not present in C++, and that is the use of static class initializers (a block of code at class level surrounded by static { ... }). In Java that block of code will be executed when the class is loaded and only once. Initialization of static member variables in C++ must be done in the initializer of the variable definition.
This stuff seems to be fairly well covered here.
But to paraphrase, there are 2 uses in C
Prevent the use of a global variable outside the scope of the file that defines it.
Allow local variables within a function to persist accross invocations of the function, as in
int getNextId()
{
static int id = 0;
return id++;
}
C++ inherits both of these, and adds two uses of its own.
static member variables: Variables that are "shared" accross all instances of a class, and can also be accesses without reference to an instance of the class. Shared seems like the wrong word, but in essence I beleive that the result is that any reference to a static member variable references the same memory location.
static methods: Methods that can be called without reference to a specific instance of the class that defines it.
Static basically means that a variable is tied to the lifetime of the program and not of any given function or class instance. When should you use it? Don't. What is the purpose? Debugging data, mostly.
Generally, in C++, if you find yourself using static data, you've done it wrong. There are times when it's appropriate, but they're very rare.
When static is used in a class in C++, it means more or less the same thing that it does in Java. For variables it means that one one instance of the variable exists for all classes and for functions, it means that the function does not implicitly access the this pointer at all.
In C and C++ when static is used for a global variable or function, then it means that the variable may only be referenced in the current C or C++ file. In other words, the compiler must not generate any relocation symbols for the variable or function.
When static is used next to a variable in a local function, it means that the variable does not go out of scope but will retain its value from function-call to function-call. The variable become effectively a global variable that can only be accessed from the given function.
Static class members are data and functions that are associated with the class itself, rather than with the objects of the class.
In the following example, class Fred has a static data member x_ and an instance data member y_. There is only one copy of Fred::x_ regardless of how many Fred objects are created (including no Fred objects), but there is one y_ per Fred object. Thus x_ is said to be associated with the class and y_ is said to be associated with an individual object of the class. Similarly class Fred has a static member function f() and an instance member function g().
class Fred {
public:
static void f() throw(); <-- 1
void g() throw(); <-- 2
protected:
static int x_; <-- 3
int y_; <-- 4
};
(1) Member function associated with the class
(2) Member function associated with an individual object of the class
(3) Data member associated with the class
(4) Data member associated with an individual object of the class
Usage:
When you want to keep tract of the number of instances of a class created you use static variable. For example in a 'Car' class each Car instance may have a unique serial number(_y in this case) and the company may want to keep track of the number of cars produced(_x in this case).