Initialization of a static member inside a global function - c++

My code looks like this:
class myClass{
public:
static int a;
};
void myFunc()
{
int myClass::a = 1;
}
I see the following compilation error
error C2655: 'myClass::a' : definition or redeclaration illegal in current scope
I make the following change and everything goes fine. Any idea?
class myClass{
public:
static int a;
};
int myClass::a = 1;
void myFunc()
{
}

Logically think like this:
If you never call myFunc(), myClass::a is not defined. So it must be in global scope.
In your first code snippet, potentially you may use myClass::a even without defining it, so it not allowed and former syntax is not valid C++.

Static variable must be initialized before program start, so if you initialized it in a function, there is chance that it will not be initialized at all. So the compiler should pose this as an error. Static variable is allocated at compile time (before program run). Hope this help.

If you define the static member data in a function, it's linkage is internal to the function. The linkage required for them is global.

Related

Why do we need to define a static variable of a class, unlike the other member of a class?

Whenever we have a class with some static member variable, why do we need to define it?
Why can't we use it directly?
I wanted to see if any memory space would be allocated to the static variable if I don't define it, so I wrote this little code and it seems like memory is indeed allocated for the variable.
#include <iostream>
using namespace std;
class A
{
public:
int a;
static int b;
};
// int A::b = 1;
int main()
{
cout<<sizeof(A::b);
return 0;
}
Output:
4
Now, I defined the variable and initialized it (uncommented the int A::b = 1; line) and ran the same code, even this time the output was the same.
So, what is the purpose behind defining it?
The definition is required if the variable is odr-used, while sizeof(A::b) doesn't.
One and only one definition of every non-inline function or variable that is odr-used (see below) is required to appear in the entire program (including any standard and user-defined libraries). The compiler is not required to diagnose this violation, but the behavior of the program that violates it is undefined.
For example, if you take address of the variable, then it's odr-used and it must be defined.
cout << &A::b;
For static data member you have to allocate memory for it in your implementation, what you are doing now does not allocate memory but you are just getting the size of the int.
In C++ 17 you can declare static variable inline, for int its default value is zero but you can set any value you want. Like this:
static inline int b=4;

what's the proper way to declare static mutable values

I've got a mutable static value in my program.
static int foo = 0;
regardless of private or public accessibility I don't want nasty name collisions.
I don't like things just sitting in the scope of my namespace.
So I tried the following
class aClass{
static int foo = 0;
}
Apperantly this is impossible, unless I don't assign a variable to foo.
Which is impossible for foo in my program.
What is the standard on declaring mutable statics with a default value?
I read something about people using const <T>* but that doesn't sound sane to me, and seems prone to error.
how about header:
class aClass {
static int foo;
}
cpp file
int aClass::foo;
you can then add an initialisation if you want to there.

Static object declaration only causing no error

Why the code is not causing compile error?
#include<iostream>
class x{
private:
int v;
public:
x():v(7){};
};
class b{
private:
static x as;
int a;
public:
b():a(8){};
};
//x b::as;
int main(){
b g;
return 0;
}
Even after commenting the particular line x b::as code works which I think it should as I haven't define/initiate my static object which is necessary. Why is it so?
And what if I initiate non-static object using static object like static x asd; x bv=asd; ?
The program compiles and runs fine because it doesn't actually violate any rules. The key rule here is, in [basic.def.odr]:
Every program shall contain exactly one definition of every non-inline function or variable that is odr-used
in that program; no diagnostic required.
In your program, b::as is not odr-used yet. However, as soon as you use it somewhere (maybe you take its address, or try to access as.v, etc), then you violate this condition because you didn't provide a definition for as.
It wil not ever cause a error until you use it (b::as) in your code. Then, linker will not able to find it's definition and cause a unresolved reference error:
undefined reference to b::as
If you will try to initialize a non-static class member by static one, here is the same behaviour:
If you define your static member here is no error.
If you don't do that, there would be a unresolved reference error.
class b {
private:
static x as;
int a = b::as;
public:
b():a(8){};
};
x b::as; // this is now correct but if you comment this, you should can't initialize `b::a` with `b::as` then because it will cause a unresolved reference error.

Declaring static class variables

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.

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.