Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Static Data Member Initialization

Tags:

Why must static data member initialization be outside the class?

class X { public:       int normalValue = 5; //NSDMI       static int i; };  int X::i = 0; 

Why is the static data member (here "i") only a declaration, not a definition?

like image 764
CyberGuy Avatar asked Jul 02 '12 20:07

CyberGuy


People also ask

Is a static data member it can only be initialized?

8.1: Static data. Any data member of a class can be declared static ; be it in the public or private section of the class interface. Such a data member is created and initialized only once, in contrast to non-static data members which are created again and again for each object of the class.

How do you declare a static data member in C++?

Static Data Members in C++ The static data member is always initialized to zero when the first class object is created. static data_type data_member_name; In the above syntax, static keyword is used. The data_type is the C++ data type such as int, float etc.

How static variables are initialized?

A static variable in a block is initialized only one time, prior to program execution, whereas an auto variable that has an initializer is initialized every time it comes into existence. A static object of class type will use the default constructor if you do not initialize it.


1 Answers

It's important to distinguish the initializer which says what its initial value is, and the definition. This modified code is valid, with the initializer in the class definition:

class X { public:   int normalValue = 5;   static const int i = 0;       // declaration, with initializer };  const int X::i;                 // definition 

i.e. What must be outside the class is a definition, not the initialization.

That's because a variable must have an address in memory (unless it's only used in limited situations, such as in compile-time constant expressions.)

A non-static member variable exists inside the object it is a member of, so its address depends on the address of the object that contains it. Every time you create a new X you also create a new X::normalValue variable. The non-static data member's lifetime begins with the class' constructor. NSDMI syntax doesn't have anything to do with the variable's address in memory, it just allows you to provide an initial value in one place, instead of repeating it in every constructor with an explicit constructor initializer list.

On the other hand, a static member variable is not contained within an instance of the class, it exists independently of any single instance and exists from the start of the program, at a fixed address. In order for a static member variable (or any other global object) to get a unique address the linker must see exactly one definition of the static variable, in exactly one object file, and assign it an address.

Because a static variable needs exactly one definition in exactly one object file, it doesn't make sense to allow that definition to be provided in the class, since class definitions typically exist in header files and are included in multiple object files. So although you can provide an initializer in the class, you still need to define the static data member somewhere.

You can also look at it like declaring an extern variable:

namespace X {   extern int i; } 

This declares the variable, but there must be a definition somewhere in the program:

int X::i = 0; 
like image 65
Jonathan Wakely Avatar answered Oct 20 '22 05:10

Jonathan Wakely