C ++ static

Source: Internet
Author: User

This article is from an excellent post of CU, which summarizes the static knowledge in a comprehensive manner, so I will share it with you.
Generally, static refers to the concept of static storage. In fact, static in c ++ contains two meanings.
1) allocation on fixed addresses, which means that objects are created in a special static region, instead of dynamically created on the stack during each function call, this is the concept of static storage.
2) static controls the object's visibility into the connector. A static object is always a local range for a specific compilation unit. This range includes a local file or a local class, files or classes that exceed this range cannot see static objects. This also describes the concept of connection, which determines what names can be seen by the connector.
I. About static storage
For a complete program, the dynamic data generated by malloc and realloc of the general program is stored in the heap zone. The local data of the program is the data stored in the stack zone of each function, partial data objects usually release space as the function exits. For static data, even objects in the function are stored in the global data zone, the data in the global data zone does not release the space because the function exits.
The file scope object of C. The Global (namespace scope) variables of C ++ have a static storage period. For the static storage period, the c and c ++ standards are described as follows:
ISO C11 (N1570)
6.2.4
3 An object whose identifier is declared without the storage-class specifier _ Thread_local, and either with external or internal linkage or with the storage-class specifier static, has static storage duration. its lifetime is the entire execution of the program and its stored value is initialized only once, prior to program startup.
Iso c ++ 11
3.7.1 Static storage duration [basic. stc. static]
1 All variables which do not have dynamic storage duration, do not have thread storage duration, and are not local have static storage duration. the storage for these entities shall last for the duration of the program (3.6.2, 3.6.3 ).
2. Static variables in the function
Generally, when defining a variable in a function, the compiler enables the stack pointer to move down an appropriate position during each function call to allocate memory for these internal variables. If this variable is an initialization expression, the program needs to initialize the expression whenever the program runs here. In this case, the variable value cannot be saved between two calls.
Sometimes we need to save the value of the variable between two calls. The general idea is to define a global variable for implementation. In this way, the variable no longer belongs to the function itself, and is no longer only controlled by the function. Therefore, it is necessary to declare the variable as a static object so that the object will be saved in the static storage area, rather than in the stack. Object initialization is only performed when the first function is called. Each value is retained until the new value overwrites it. The following example explains this.
 
1 //************************************* ***
2
3 // 1.cpp
4
5 //************************************* ***
6
7 # include <iostream. h>;
8
9 void add_n (void );
10
11 void main (){
12
13 int n = 0;
14
15 add_n ();
16
17 add_n ();
18
19 add_n ();
20
21}
22
23 void add_n (void ){
24
25 static int n = 50;
26
27 cout <"n =" <n <endl;
28
29 n ++;
30
31}
 
 
The program running result is:
1. n = 50
2. n = 51
3. n = 52;
From the preceding running results, we can see that static n is indeed the last value in each call. If the predefined static variable does not provide an initial value, the compiler will ensure that it will be initialized with a zero value during initialization. Static variables must be initialized, but the zero-value Initialization is only valid for the predefined types of the system, such as int, char, and bool. In fact, we only use these predefined types. In most cases, we may use structure, union, class, and other user-defined types. For these types, users must use constructors for initialization. If you do not specify the parameters of the constructor when defining a static object, you must use the default constructor. If the default constructor does not exist, an error occurs. Let's look at the example below.
 
1 //************************************* *************
2
3 # include <isotream. h>;
4
5 class x {
6
7 int I;
8
9 public:
10
11 x (int I = 0): I (I ){
12
13 cout <"I =" <I <endl;
14
15} // default constructor
16
17 ~ X () {cout <"x ::~ X () "<endl;
18
19 };
20
21 void fn (){
22
23 static x x1 (47 );
24
25 static x x2;
26
27}
28
29 main (){
30
31 fn ();
32
33}
 
 
The program running result is as follows:
1. I = 47
2. I = 0
3. x ::~ X ()
4. x ::~ X ()
From the preceding example, we can see that static x objects can be initialized using constructors with parameters, such as x1 or the default constructor, such as x2. When the program controls the definition point of the object for the first time, and the constructor must be executed only for the first time. If the object has no constructor with parameters and no default constructor, the program will not be able to compile.
3. Static members in the class
The concept of static storage can be further referenced in the class. In c ++, the objects of each class are copies of the members of the class. Generally, they have no relationship with each other, but sometimes we need to share some data between them, we can implement this through global variables, but this result is that the program is insecure, because any function can access and modify this variable, and it is easy to conflict with other names in the project. Therefore, we need a best-of-breed method that can be stored as global data variables and hidden inside the class, associate with the class itself, so that only the class object can manipulate this variable, thus increasing the security of the variable.
Such variables are called static members of the class. Static members include static data members and static member functions. All static data members of the class have a single bucket, regardless of the number of class objects, which share the storage area. Therefore, changing the static members of objects in each class will affect other objects. Let's take a look at the example below.
 
 
1 //************************************* *
2
3 // student. cpp
4
5 //************************************* *
6
7 # include <iostream. h>;
8
9 # include <string. h>;
10
11 class student {
12
13 public:
14
15 student (char * pname = "no name "){
16
17 cout <"create one student" <endl;
18
19 strcpy (name, pname );
20
21 number ++;
22
23 cout <number <endl;
24
25}
26
27 ~ Student (){
28
29 cout <"destruct one student" <endl;
30
31 number --;
32
33 cout <number <endl;
34
35}
36
37 static number (){
38
39 return number ;}
40
41 protected:
42
43 char nme [40]
44
45 static int number;
46
47 };
48
49 void fn (){
50
51 student s1;
52
53 student s2;
54
55 cout <student: number <endl;
56
57}
58
59 main (){
60
61 fn ();
62
63 cout <student: number <endl;
64
65}
 
 
The program output result is as follows:
Create one student
1
Create one student
2
2
Destruct one student
1
Destruct one student
0
0
In the above Code, we use static member variables and static member functions. Next we will first describe static data members.
Iv. static member variables
In the code, we can see that number is neither an object s1 nor a part of object s2, it belongs to the student class. Each student object has a name Member, but only one number member. All student objects share this member. S1.number is equivalent to s2.number. The student object space does not reserve space for the number member. Its space allocation is not completed in the student constructor, and space collection is not completed in the destructor. Therefore, unlike the name Member, it does not produce or disappear with the generation or disappearance of the object.
Because the space of static data members is allocated in the global data zone, it must exist when the program starts running, therefore, the space allocation and initialization of static members cannot be completed in the function including the main function, because the function is called in the program to allocate space for internal objects. In this way, the space allocation and initialization of static members can only be performed in the following three ways. First, the header file of the class's external interface, where the class definition is declared. Second, the internal implementation of the class definition, where the class member function is defined and implemented. Third, the global data description and definition before the main () function of the application. Because static data members must actually allocate space, it is impossible to allocate memory in class definition header files. On the other hand, it cannot be the external definition of Class declaration in the header file, because it will lead to repeated definitions of multiple source programs using this class. Static data members cannot be defined in the global data Declaration of the main () function. In that case, every program using this class must define the static members of this class in the global data Declaration of the main () function of the program. This is unrealistic. The only way is to put the definition of static data members in the implementation of the class. Use the class name for guidance during definition, and include the header file When referencing.
For example:
1 class {
2 static int I;
3 public:
4 //
5}
 
In the class definition file, int a: I = 1;
Note that
1. static data members must be defined only once. If they are repeatedly defined, the connector reports an error. At the same time, their initialization must be completed during the definition. If no value is assigned to a static data member of the predefined type, the value is null. The user-defined type must be assigned a value through the constructor. If no constructor includes the default constructor, compilation fails.
2. static data members are not allowed in local classes. Because static data members must exist when the program is running, the program cannot allocate space for static data members in the local class. The following code is not allowed.
 
1 void fn (){
2
3 class foo {
4
5 static int I; // The definition is invalid.
6
7 public:
8 //
9}
10
11}
 
 
5. static member functions
Like static member variables, we can also create a static function member that serves all classes rather than specific objects of a class. Static function members, like static members, are internal implementation of the class and are part of the class definition. Number () in student. cpp is a static member function, which is defined at the same position as a common member function.
A common member function generally implies a this pointer, which points to the object itself of the class, because a common member function always belongs to a specific object of a class. Generally, this is the default value. For example, the add () function is actually written as this. add (). however, compared with normal functions, static member functions do not have the this pointer because they are not associated with any objects. In this sense, it cannot access non-static data members of a specific class object, nor can it access non-static member functions. It can only call other static member functions. The following code:
 
1 class x {
2
3 int I;
4
5 static int j;
6
7 public:
8
9 x (int I = 0): I (I ){
10
11 j = I
12
13} // non-static member functions can access static function members and static data members.
14
15 int val () const {return I ;}
16
17 static int incr (){
18
19 I ++; // The error code. Because I is a non-static member, incr () is not used as a static member function.
20
21 // access it.
22
23 return ++ j;
24
25}
26
27 static int fn (){
28
29 return incr (); // valid access because fn () and incr () can access each other as static member functions.
30
31 // question.
32
33}
34
35 };
36
37 int x: j = 0;
38
39 main (){......}
 
 
Based on the above procedures, we can summarize the following points:
1. Mutual access between static members includes access to static data members by static member functions and access to static member functions.
2. Non-static member functions can access static member functions and static data members at will.
3. static member functions cannot access non-static member functions and non-static data members.
Without the additional overhead of this pointer, static member functions increase slightly compared with global functions.

6. Understanding control connections
Before understanding how to control connections, let's take a look at the concept of External Storage types. Generally, when the program size is small, we can use a source program to fully express it. But in fact, a slightly valuable program cannot be expressed by only one program, but is divided into many small modules, each module completes a specific function, forming a source file. All source files share a main function. In order to communicate data or functions with each other between different source files, the data or function is usually declared as extern, so that the data or function declared with extern is a global variable or function. By default, the function declaration is always extern. Global data and functions defined within the file range are visible to all compilation units in the program. This is what we call external connections.
However, sometimes we may want to restrict the visibility of a name object and make it visible to an object within the local file range, so that all functions in this file can use this object, however, you do not want other files outside the local file to see or access this object, or you have defined a global object to prevent internal name objects from conflict with it.
By adding static before the global variable, we can do this. Within the scope of the file, the name of an object or function declared as static is a local variable for the compilation unit. We call it all static variables. These names use internal connections instead of external connections by default. The following example shows how static controls the connection.
The project file "first. prj" consists of two source files.
 
1 // exam1.cpp
2
3 // exam2.cpp
4
5 //************************************* **
6
7 // exam1.cpp
8
9 //************************************* **
10
11 # include <iostream. h>;
12
13 int n;
14
15 void print_n ();
16
17 void main ()
18
19 {
20
21 n = 20;
22
23 cout <n <endl;
24
25 print_n ();
26
27}
28
29
30
31 //************************************* ***
32
33 // exam2.cpp
34
35 //************************************* ***
36
37 static int n;
38
39 static void staticfn ();
40
41 void print_n ()
42
43 {
44
45 n ++;
46
47 cout <n <endl;
48
49 staticfn ();
50
51}
52
53 void staticfn ()
54
55 {
56
57 cout <n ++ <endl;
58
59}
 
 
The program running result is as follows:
1. 20
2. 1
3. 1
Next we will make a small number of changes to the above program, and look at the implementation results.
Transformation 1:
1. Change int n in the second line of exam1.cpp to extern int n, which tells the program that I declare the variable n here, but the actual definition process is in another file. Here is exam2.cpp. But in fact, exam2.cpp only declares static int n. Let's look at the running results. In vc
An error "Variable n cannot be found. This indicates that exam1.cpp cannot share the static int n variable in exam2.cpp.
Transformation 2:
1. We add void staticfn () between the second and third rows of exam1.cpp, and add a staticfn () call between the eighth and ninth rows. Check the execution result again. Vc will generate an error where the staticfn function cannot be found. This indicates that exam1.cpp cannot share staticfn () in exam2.cpp ().
From the above conclusions, we can see the following points:
1. static solves name conflicts. This allows you to create and use the same name as other source files or even global variables in the source file without causing any conflict. This is very useful in large projects.
2. A function declared as static cannot be called by other source files, because its name is only visible to local files, and other files cannot get its name, so it is impossible to connect.
3. The inline Function declared in the file scope is regarded as static by default. The const constants declared in the file scope are also static storage by default.

 

 

From Moon_Bird

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.