Why Static Variable Needs to Be Explicitly Defined

Why static variable needs to be explicitly defined?

From the beginning of time C++ language, just like C, was built on the principle of independent translation. Each translation unit is compiled by the compiler proper independently, without any knowledge of other translation units. The whole program only comes together later, at linking stage. Linking stage is the earliest stage at which the entire program is seen by linker (it is seen as collection of object files prepared by the compiler proper).

In order to support this principle of independent translation, each entity with external linkage has to be defined in one translation unit, and in only one translation unit. The user is responsible for distributing such entities between different translation units. It is considered a part of user intent, i.e. the user is supposed to decide which translation unit (and object file) will contain each definition.

The same applies to static members of the class. Static members of the class are entities with external linkage. The compiler expects you to define that entity in some translation unit. The whole purpose of this feature is to give you the opportunity to choose that translation unit. The compiler cannot choose it for you. It is, again, a part of your intent, something you have to tell the compiler.

This is no longer as critical as it used to be a while ago, since the language is now designed to deal with (and eliminate) large amount of identical definitions (templates, inline functions, etc.), but the One Definition Rule is still rooted in the principle of independent translation.

In addition to the above, in C++ language the point at which you define your variable will determine the order of its initialization with regard to other variables defined in the same translation unit. This is also a part of user intent, i.e. something the compiler cannot decide without your help.


Starting from C++17 you can declare your static members as inline. This eliminates the need for a separate definition. By declaring them in that fashion you effectively tell compiler that you don't care where this member is physically defined and, consequently, don't care about its initialization order.

Why do we need to define static variables of a class, but we don't define static variables when they are inside functions?

The static member variable instance declared inside class Singleton in Code 1 is a class variable.

This means that regardless of the state of different instances of class Singleton, the state of static variable will remain the same for all objects/instances of that particular class. Hence, it needs to be defined outside the class.
(Just like a global variable which is available to function of all scopes.). A single copy of static member variable is allocated in memory even if you don't create any instance. Their definition persists through the entire file.

In Code 2, the static variable instance is not a class variable but is simply a local variable inside a static member function. Hence there is no need for it to be defined outside since its scope is limited only to static Singleton &GetInstance() function.

Why static members need to be initialized out of the class

What you call initialization is really a definition.

And the reason is that definitions can only be done once is a single translation unit.

If the static member variable were defined in the header file it could be defined multiple times breaking the one definition rule.

Or the compiler would not know which translation unit to put the definition in, since it doesn't know anything about other possible translation units.

Why we declare static variable in a class & the definition in outside of the class?

I'm not sure but my guess is, because inside a class member variables are only declared. They are initialized through a constructor or other member functions.

This happens when an object is instantiated. However for static members, the objects need not be instantiated. Hence they need to be initialized once outside of the class.

EDIT:
Actually it is not necessary to initialize the static variables, but it is necessary to define them outside the class to allocate memory for them. Only after their definition, can they be initialized and then used in the program.

why static variable in a class gives a linking error?

First of all the definition of static variable is wrong.
Instead of my_class::m_fid = 0; you should define as int my_class::m_fid = 0; when you do that there will be no more linker error..

Another thing as per standard...

The definition for a static data member shall appear in a namespace
scope enclosing the member’s class definition.

Why should I initialize static class variables in C++?

At class scope,

int MyClass::classVar = 0;  // Why I have to init it here?

is a definition and

static int classVar;

is a declaration, ie. a promise the variable will be defined somewhere: you must define exactly once the variables you declare.

The rationale is that the class declaration will likely be included in multiple source files. Would a part of it be a definition, it would take place multiply: this is erroneous (exceptions are inline [member] functions).

Note that according to value initialization rules, you can get along with

int MyClass::classVar;  // Zero-initialized !

as a definition.

Variables declared at namespace scope are definitions too (unless they are extern qualified):

int var;

is a declaration, and a definition: if you put this into a header and include it in multiple translation units, you have an error ("multiply defined symbol", or something along those lines).

[Note that in C++ (and not in C), if the var above is const, it becomes automatically static and there is no violation of the One Definition Rule should it be put into a multiply included header. This goes slightly off topic, but feel free to ask details]

Why does the value of this static variable not change?

Static local variables are defined once and only once for a function, when the function is first called. Once it's defined and initialized it will never be redefined or reinitialized.

To modify the value of any variable, static or not, one must assign to it.

static variable instantiation outside class

This line:

static int staticVal;

inside the class is a declaration, not a definition. That's why you have to define it outside the class like this:

template<typename T> 
int TestStatic<T>::staticVal = 0;

And yes, this will generate a definition of the member for all types T.

Alternatively, you could define the static variable inline, like this:

template <typename T>
class TestStatic {
public:
inline static int staticVal = 0;
};

which has the same semantics as above, but let's you avoid having to define the static variable separately outside the class.

Why don't we have to declare static functions the same way we need to declare static variables in c++?

Static member functions are ordinary functions at the assembly level. The difference is only the hidden pointer 'this' that does not exist in them. They are basically global functions that exist like any other non static or non member (and not inline) function within the C++scope of a class name. Function scopes are C++ thing, they are not there at the CPU level.

Static variables are different. They exist before any class object is created. They are not created when a class instance is created. They are there as globals.

Perhaps it's done the way it's done to emphasize that difference.



Related Topics



Leave a reply



Submit