This question already has answers here:
static and extern global variables in C and C++
(2 answers)
Closed 2 years ago.
test1.hpp
struct obj{
obj(){}
~obj(){cout<<"destroyed"<<endl;}
};
static obj x;
test1.cpp
#include "test1.hpp"
main.cpp
#include "test1.hpp"
int main(){...}
the destructor is getting called twice, why is this happening?
gcc-7.5.0
os-ubuntu
why is this happening?
Because the variable is declared static. This means that the variable has internal linkage. Which means that each translation unit has their own object. You have defined the variable in two translation units, and therefore you have two objects.
If you didn't want this, then the variable shouldn't be static. An easy solution is to declare it inline instead. This allows it to have external linkage while still being defined in the header.
P.S. Be very careful of Static Initialisation Order Fiasco. Try to avoid variables of static storage when you can, especially those in namespace scope.
You have two static variables with the internal linkage due to defining the corresponding object in the header
struct obj{
obj(){}
~obj(){cout<<"destroyed"<<endl;}
};
static obj x;
This header is included in two modules test1.cpp and main.cpp. So each module has its own static variable x.
If you want to have one object with the external linkage then declare it in the header like
extern obj x;
and define it in one of modules like
obj x;
Related
This question already has answers here:
C++ static member variable and its initialization
(5 answers)
How to initialize private static members in C++?
(18 answers)
Closed 5 years ago.
I know that non-constant static variables need to be initialized outside the class definition but, is there a reason for this?
class A {
static int x = 0 // compile error;
static int y;
};
int A::y = 0; // fine
Essentially it's because x exists independently of the number of instances of A that are created.
So storage for x needs to be defined somewhere - you can't rely on an instance of A to do that, and that's what
A::x = 0;
in exactly one translation unit, does.
When the const qualifier is present, the static variable can be considered as a constant expression. Initializing it in the class definition goes to that effect. It's just some constant value, may not even need any storage.
But in the other case, it's not a constant expression. It definitely needs storage. And as #Bathsheba points out, it needs to be defined in only one translation unit (pre-C++17). Generally speaking, a declaration that contains an initializer is also a definition. So it just can't be initialized when declared.
Starting with C++17, that variable can be an inline variable. So the definition can in fact be included with the class declaration
class A {
static inline int x = 0;
};
And the compiler will sort out all those declarations to mean the same storage.
after a small research, found this (from bogotobogo) :
we cannot initialize a static member variable inside the class declaration. That's because the declaration is a description of how memory is to be allocated, but it doesn't allocate memory. We allocate and initialize memory by creating an object using that format.
In the case of a static class member, we initialize the static member independently, with a separate statement outside the class declaration. That's because the static class member is stored separately rather than as part of an object.
The exception to the initialization of a static data member inside the class declaration is if the static data member is a const of integral or enumeration type.
my take from this is ..
static members exist as members of the class rather than as an instance in each object of the class.
when you initialize the static variable inside the class declaration, as a concept it will be re-initialized (not the actual behaviour) on every creation of an object/instance of the class,
[since the class declaration is the blueprint of which every new object of the class is construct].
but we know that this is not supposed to be the behavior of a static member, so the initialization of this member is outside of the class declaration.
I found this explanation a more intuitive one, but still the formal explanation remains the first one.
Apart from what others have said, there is currently no place (pre C++ 11) within a class where you could initialize a static member (because members (both static and non-static can't be initialized where declared). For non-static members, we use either the constructor or the member initializer list to do the initialization. But this means we have to create an instance of the class.
Since a static member initialization can't depend on an instance being created, it's done outside the class where the member is declared.
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 8 years ago.
Why is it giving me a linking error? I think it's OK to access static members with this->x. Logically it sounds OK. I guess an instance pointer can access what a class owns as per OOPS concepts.
You need to also define the static member variable. For example:
// in .h
class some_class {
static int v; // it's just a declaration
};
// in .cpp
int some_class::v; // here's the defination
Put declarations in your Foo.h file:
class Foo {
static int v;
};
Put defenitions in your Foo.cpp file:
int Foo::v;
Here are some explanations: Why the static data members have to be defined outside the class separately in C++, Defining static members in C++
I find it helpful to treat linking errors differently. If you do something against the rules of the language -- the compilation error will be issued, so if you get a linking error it must be not something that you've done against the rules of the language directly, rather than you've omitted something. And usually the error message tells you what exactly you have omitted.
This question already has answers here:
Undefined reference to static variable [duplicate]
(2 answers)
Closed 9 years ago.
I am beginner to C++ and have a doubt about static member variables and member functions.
I have implemented a class as follows -
class Foo
{
private:
static int myVariable;
public:
static void setMyVariable()
{
myVariable = 100;
}
static void resetMyVariable()
{
myVariable = 0;
}
};
There are following considerations when I wrote a code like that -
I want only one instance of class Foo. Thats why I made all member variables and functions as static.
I don't want the outside code to touch myVariable
I have put this class in a header file and included in my main file. When I do this, I get an error undefined reference to Foo::myVariable
I want to know if I can write a code which can satisfy above requirements?
Thanks !
You need to define static class variables somewhere:
e.g. in your main C++ file,
int Foo::myVariable;
Note that technically, by making everything static, you may have no instances of Foo.
This question already has answers here:
Declaring static data members of normal class and class template
(2 answers)
Closed 9 years ago.
// A.h
class A {
public:
static int a;
};
int A::a = 0;
If I try to include A.h in multiple .cpp files, link would fail with multiple definition of A::a. I think this makes sense because each .obj file contains A::a
However, I could use a template,
// A.h
template<class T>
class A {
public:
static T a;
};
template<class T>
T A<T>::a = 0;
I can now include A.h in multiple .cpp files and also I can assign the value A<int>::a = 100; in one .cpp file and get the same value in another one with A<int>::a.
When does template make such difference?
Is there only 1 copy of this static variable? Which .obj will keep this variable?
Is the constructor called only once? If the initial value is different, which one wins?
When does template make such difference?
Always. I suppose I don't understand the question.
Is there only 1 copy of this static variable?
Only one copy in the final program for each distinct type T the template was instantiated with.
Which .obj will keep this variable?
All of them that were generated from translation units where the template was instantiated. The linker then chooses one and discards all others.
Is the constructor called only once?
Once for each specialization.
If the initial value is different, which one wins?
That would be a violation of the One Definition Rule. Such a program would be ill-formed, no diagnostic required.
Why not define static member in the souce file that implements the class A? Then you should be able to include A.h in multiple source files w/o problem.
// A.h
class A {
public:
static int a;
};
// A.cpp
int A::a = 0;
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Initializing private static members
Why I can't initialize non-const static member or static array in class?
It is strange to me. Why not assume there is a static field at the global scope?
It has to be placed somewhere (in some object file), so linker could find it. If you have declaration of class with static filed in .h file and include this file in a few .cpp files, then it would be ambiguous, which object file should have place allocated for this filed.
Please also note, that primitive type const static field could be initialized in class declaration:
class Foo
{
static const int n = 42;
};