static keyword (C++)

1. Static in process-oriented design

1. Static global variables

Add the keyword static before a global variable, and the variable is defined as a static global variable. Let’s first give an example of global variables and static global variables. For example, define static global variable i and global variable j in file A:

#include<iostream>

using namespace std;

static int i = 5;

int j = 3; //Default is extern

int main()

{

/*code*/

}

Both global variable j and static variable i are stored in the global data area of the program. Their life cycle is the entire running period of the program, but the scope of j is the global scope and can be used in other files through extern, while the scope of i The scope is file scope and can only be used in file A, for example in file B:

extern int j; //OK

extern int i; // error: i is not visible in file B

int a = j; // OK

int b = i; // error

In other words, when declaring a global static variable, static does not change its lifetime, that is, the storage location (because global variables are originally stored in the global data domain), but limits the scope of the variable to the current file.

Total: The static global variable i has the following characteristics:

  • This variable allocates memory in the global data area;
  • Uninitialized static global variables will be automatically initialized to 0 by the program (the value of the automatic variable is random unless it is explicitly initialized);
  • Static global variables are visible throughout the file in which they are declared, but not visible outside the file;

Static variables allocate memory in the global data area, including static local variables that will be mentioned later. For a complete program, the distribution in memory is as follows:

code area
global data area
Heap area
stack area

In general, the dynamic data generated by new in the program is stored in the heap area, and the automatic variables inside the function are stored in the stack area. Automatic variables generally release space as the function exits, and static data (even static local variables inside the function) are stored in the global data area. The data in the global data area will not release space when the function exits.

2. Static local variables

Add the keyword static before a local variable, and the variable is defined as a static local variable. Let’s give an example of a static local variable, as follows:

#include<iostream>

using namespace std;

void fun()

{

int i = 1; // Local variable, with dynamic lifetime, initialized every time when entering the function

static int j = 2; //Static local variables have global lifespan, are locally visible, and are only initialized when entering the function for the first time.

}

int main()

{

static int j; //Static local variable, has global life and is locally visible

}

Usually, a variable is defined in the function body, and stack memory is allocated to the local variable every time the program runs to the statement. But as the program exits the function body, the system will reclaim the stack memory and local variables will become invalid accordingly.

But sometimes we need to save the value of a variable between calls. The usual idea is to define a global variable to do this. But in this way, the variables no longer belong to the function itself and are no longer only controlled by the function, which brings inconvenience to the maintenance of the program.

Static local variables can solve this problem. Static local variables are saved in the global data area instead of on the stack. Each value is kept until the next call until a new value is assigned next time.

Static local variables have the following characteristics:

  • This variable allocates memory in the global data area;
  • Static local variables are initialized for the first time when the program is executed to the declaration of the object, that is, subsequent function calls will no longer be initialized;
  • Static local variables are generally initialized at the point of declaration. If not explicitly initialized, they will be automatically initialized to 0 by the program;
  • It always resides in the global data area until the end of the program. But its scope is a local scope. When the function or statement block that defines it ends, its scope ends;

3. Static function

By adding the static keyword before the return type of a function, the function is defined as a static function. A static function is different from an ordinary function in that it can only be visible in the file in which it is declared and cannot be used by other files.

Example of static function:

#include<iostream>

using namespace std;

static void fun()

{

/*code*/

}

int main()

{

/*code*/

}

Benefits of defining static functions:

  • Static functions cannot be used by other files;
  • Functions with the same name can be defined in other files without conflict;

2. Object-oriented static keyword (static keyword in class)

1. Static data members

Add the keyword static before the declaration of a data member in a class, and the data member is a static data member in the class. Let’s first give an example of a static data member.

#include<iostream>

using namespace std;


class point

{

public:

Point(int xx = 0, int yy = 0) { X = xx; Y = yy; countP + + ; }

Point(Point &p);

~Point() { countP --; }

int GetX() { return X; }

int GetY() { return Y; }

void GetC() { cout << "Object id = " << countP << endl; } //Output static data members

private:

int X, Y;

static int countP; //Static data member declaration, used to record the number of points

};


Point :: Point(Point & amp;p)

{

X = p.X;

Y = p.Y;

countP + + ; //Accumulate countP in the constructor, and all objects jointly maintain the same countP

}


int Point::countP = 0; //Static data member definition and initialization, use class name qualification


int main()

{

Point A(4, 5); // Define object A, its constructor will increase countP by 1

A.GetC(); //Output the number of objects

Point B(A); //Define object B, its constructor will increase countP by 1

B.GetC();


return 0;

}

Static data members have the following characteristics:

For non-static data members, each class object has its own copy. Static data members are treated as members of the class. No matter how many objects of this class are defined, there is only one copy of the static data members in the program, which is shared and accessed by all objects of this type. In other words, static data members are common to all objects of this class. For multiple objects of this class, static data members are allocated memory only once and are shared by all objects. Therefore, the value of static data members is the same for every object, and its value can be updated;

Static data members are stored in the global data area. Static data members need to allocate space when they are defined, so they cannot be defined in the class declaration. In the above example, the statement int Point::countP=0; defines a static data member;

Static data members follow the same public, protected, and private access rules as ordinary data members;

Because the static data member allocates memory in the global data area and is shared by all objects belonging to this class, it does not belong to a specific class object. Its scope is visible when no class object is generated, that is, when no instance of the class is generated. We can then operate it;

Static data member initialization is different from general data member initialization. The format of static data member initialization is:

::=

There are two access forms for static data members of a class:

. or ::

If the access rights of static data members are allowed (that is, public members), static data members can be referenced in the program according to the above format;

Static data members are mainly used when each object has the same certain attribute. For example, for a deposit class, the interest rate for each instance is the same. Therefore, interest should be set as a static data member of the deposit class. This has two advantages. First, no matter how many deposit class objects are defined, the interest data members all share the memory allocated in the global data area, thus saving storage space. Second, once the interest needs to be changed, as long as it is changed once, the interest of all deposit objects will be changed;

Compared with global variables, using static data members has two advantages:

Static data members do not enter the global name space of the program, so there is no possibility of conflict with other global names in the program;

Information hiding can be achieved. Static data members can be private members, but global variables cannot;

2. Static member function

Like static data members, we can also create a static member function that serves the entire class rather than serving specific objects of a certain class. Static member functions, like static data members, are internal implementations of the class and are part of the class definition. Ordinary member functions generally imply a this pointer, which points to the object of the class itself, because ordinary member functions always specifically belong to a specific object of a certain class. Normally, this is the default. For example, the function fn() is actually this->fn(). But compared with ordinary functions, static member functions do not have this pointers because they are not associated with any object. In this sense, it cannot access non-static data members belonging to the class object, nor can it access non-static member functions, it can only call the remaining static member functions.

class A{

public:

static void fun(A a);

private:

int x;

};


void A :: fun( A a){

cout << x; //The reference to x is wrong

cout << a.x; //Correct

}

Regarding static member functions, it can be summarized as follows:

Function definitions that appear outside the class cannot specify the keyword static;
Static members can access each other, including static member functions accessing static data members and accessing static member functions;
Non-static member functions can access static member functions and static data members arbitrarily;
Static member functions cannot access non-static member functions and non-static data members;
Since there is no additional overhead of this pointer, static member functions will have a slight increase in speed compared with global functions of the class;
To call a static member function, you can use the member access operators (.) and (->) to call the static member function for a class object or a pointer to a class object, or you can directly use the following format:
:: ()
Call the static member function of the class.