C/C++:static用法总结

前言:static是C/C++中一个很重要的关键字,最近阅读了很多博客和资料,遂在此对自己的学习笔记进行简单的总结并发表在这里

 一、C语言中的static

静态全局变量:在全局变量之前加上关键字static,该全局变量就被定义成了一个静态全局变量

特别注意:

1.静态全局变量在内存中的存储位置:静态区(全局区)。 [注]:静态区(全局区)在整个程序运行期间都存在

2.静态全局变量的初始化:未经初始化的静态全局变量会被程序自动初始化为0。 [注]:在C语言中,未经初始化的全局变量的值是任意的;而在C++中,未经初始化的全局变量也会被程序自动初始化为0

3.全局变量和静态全局变量的存储方式是一样的,但不同的是全局变量在整个源代码中都是可以使用的,而静态全局变量只能在当前文件中使用。比如一个程序有3个文件a.cpp、b.cpp和c.cpp,如果在文件a.cpp中定义了一个全局变量x,那么变量x在文件a.cpp、b.cpp和c.cpp中都可以使用;但如果在文件a.cpp中定义了一个静态全局变量y,那么变量y只能在文件a.cpp中使用文件b.cpp和文件c.cpp都不可以使用该静态全局变量y

源文件file1.cpp:

1 // 文件file1.cpp
2 int value1=10;//全局变量value1
3 static int value2;//静态全局变量value2,默认初始化为0
4 ......

 源文件file2.cpp:

1 // 文件file2.cpp
2 extern int value1; //成功:期望使用文件file1中定义的全局变量value1
3 extern int value2; //错误:期望使用文件file1中定义的静态全局变量value2,但value2是static类型,只能在file1中使用,无法被其他文件使用
4 ......

4.使用静态全局变量的好处:

a.将一个全局变量定义为静态全局变量,相当于让该全局变量对该程序的其他源文件进行了“隐藏”,也就是说该静态全局变量只能在定义它的源文件中使用,而程序的其他源文件则无法访问该变量

b.程序中的其他源文件中可以使用与该静态全局变量同名的变量,而不会发生冲突

5.在C/C++程序中,如果一个全局变量仅仅在单个源文件中使用,则可以将该全局变量修改为静态全局变量,以降低模块间的耦合度


 • 静态局部变量:在局部变量之前加上关键字static,该局部变量就被定义成了一个静态局部变量

特别注意:

1.静态局部变量在内存中的存储位置:静态区(全局区)。[注]:普通局部变量在内存中的存储位置为栈区

2.静态局部变量的初始化:未经初始化的静态局部变量会被程序自动初始化为0。[注]:在C/C++中,未经初始化的普通局部变量值是任意的

3.static并没有改变局部变量的作用域。换句话说就是静态局部变量的作用域仍是局部作用域,当定义它的函数或语句块结束的时候,其作用域也就随之结束。 [注]:与之相反,static改变了全局变量的作用域(在声明它的文件之外是不可见的)

4.static虽然没有改变局部变量的作用域,但它改变了局部变量在内存中的存储位置(而static修饰的全局变量在内存中的存储位置则没有被static改变),即从原来的栈区中存放改变为静态区(全局区)中存放。因此静态局部变量在离开其作用域时,并没有像一般局部变量那样被销毁,而是仍驻留在内存中的静态区(全局区)中,直到程序结束,只不过在其离开自己的作用域时,我们无法再对其进行访问

 1 #include<iostream>
 2 using namespace std;
 3 int count=1;
 4 int fun(){
 5     static int count=10;
 6     return count--;
 7 }
 8 int main(){
 9     cout<<"Global	Local Static"<<endl;
10     for(int i=1;i<=10;i++){
11         cout<<"  "<<count++<<"	  "<<fun()<<endl; 
12     }
13     return 0;
14 }

5.在C/C++中,如果全局变量仅有单个函数访问,则可以将该全局变量改为该函数的静态局部变量,以降低模块间的耦合度


 • 静态函数:在函数的返回值类型前加上关键字static,该函数就被定义成了一个静态函数

特别注意:

1.和静态全局变量相似,静态函数只能在声明它的源文件中可见,而不能被该程序的其他源文件所使用。

源文件file1.cpp:

1 //文件file1.cpp
2 ......
3 extern void fun1(){......} //定义函数fun1
4 static void fun2(){......} //定义静态函数fun2
5 ......

源文件file2.cpp:

1 //文件file2.cpp
2 ......
3 extern void fun1();//成功:期望使用文件file1.cpp中的函数fun1
4 extern void fun2();//错误:期望使用文件file1.cpp中的静态函数fun2,但fun2是static类型函数,只能在file1中使用,无法被其他文件使用 

2.使用静态函数的好处:

a.在该程序的其他源文件中可以定义和使用与该静态函数同名的函数,而不会发生冲突

b.将一个普通函数定义为函数,相当于让该函数对该程序的其他源文件进行了“隐藏”,也就是说静态函数只能在定义它的源文件中使用,而程序的其他源文件则无法调用该函数

c.静态函数会被自动分配在一个一直使用的存储区域,直到程序结束。这样避免了普通函数在调用时的进栈出栈操作,从而提高程序的运行速度


 • 总结:static在C语言中的作用:

——隐藏功能:static修饰的全局变量和普通函数只能在定义它们的源文件中使用,相当于对程序中的其他源文件进行了隐藏

——默认初始化功能:static修饰的变量,不管是全局变量还是局部变量,在用户没有显式初始化它们的条件下,系统都会将他们默认初始化为0

——延长“寿命”功能:static修饰的局部变量存储在内存的静态区(全局区)而非栈区,而静态区中存储的内容只会在程序结束时被OS释放,因此当static修饰的局部变量离开自己的作用域时,其不会像一般局部变量那样被系统销毁,而是一直驻留在系统的内存中,直到程序结束。


二、C++中的static

• 静态数据成员:自定义类中被static修饰的成员变量

特别注意

1.静态数据成员在内存中的存储位置:静态区(全局区)

2.使用:

语法:类名::静态数据成员名

 3.静态数据成员属于类换句话说就是类的静态数据成员为其所有对象所共享,不管该类有多少对象,静态数据成员只有一份存储于公共的内存中

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 class Student{
 5 public:
 6     static int count;//记录该类的对象的个数
 7     Student(){
 8         count++;
 9     } 
10     Student(string name,int age):Name(name),Age(age){
11         count++;
12     }
13     ~Student(){
14         count--;
15     }
16 private:
17     string Name;
18     int Age;
19 };
20 int Student::count=0; //对count进行初始化 
21 int main(){
22     Student stu1("Tomwenxing",23);
23     Student stu2("Ellen",22);
24     Student stu3("Jack",24);
25     cout<<"Student类的对象的个数:"<<Student::count<<endl;
26     return 0;
27 }

 


 • 静态成员函数:自定义类中被static修饰的成员函数

 特别注意

1.在C++的自定义类中,一个常规的成员函数声明往往意味着:

  • 该成员函数能够访问其所在类的私有部分

  • 该成员函数位于其所在类的作用域之中

  • 该成员函数必须由一个对象去激活从而被调用(通过this指针来实现)

如果将该类的一个成员函数声明为static,则可以只让它拥有前两种性质

2.使用:

语法1:类名::静态成员函数名
语法2:对象名.静态成员函数名

3.和静态数据成员一样,静态成员函数也属于类,类的静态成员函数为其所有对象所共享

4.类中的普通成员函数既可以访问一般成员变量,也可以访问静态数据成员;而类中的静态成员函数只能访问类中的静态数据成员。

[解释]:编译器在编译程序中的自定义类时,会在类中的每个普通成员函数中插入this指针,而对static修饰的静态成员函数则不会插入this指针。由于静态成员函数中没有this指针,因此静态成员函数无法在其函数体内访问非静态数据成员;相反,由于静态数据成员属于类而非特定对象,故不需要this指针也可以在函数体内访问静态数据成员,因此不管是普通成员函数还是静态成员函数,都可以在其函数体内访问静态数据成员。

5.同理,普通成员函数中可以调用静态成员方法,而静态成员方法中不能调用普通成员函数

 1 #include<iostream>
 2 #include<string>
 3 using namespace std;
 4 class Student{
 5 public:
 6     static int count; //静态数据成员 
 7     Student(){
 8         count++;
 9     } 
10     Student(string name,int age):Name(name),Age(age){
11         count++;
12     }
13     ~Student(){
14         count--;
15     }
16     void show1();
17     static void show2(); 
18 private:
19     string Name;
20     int Age;
21 
22 };
23 int Student::count=0; //对count进行初始化 
24 /*
25 编译器对成员函数show1的改写:
26 void Student::show1(Student* const this){
27     cout<<"Name:"<<this->Name<<endl;
28     cout<<"Age:"<<this->Age<<endl;
29     cout<<"Count:"<<count<<endl;
30     show2();
31 */
32 void Student::show1(){
33     cout<<"调用了方法show1"<<endl;
34     cout<<"Name:"<<Name<<endl;
35     cout<<"Age:"<<Age<<endl;
36     cout<<"Count:"<<count<<endl; 
37     show2();//在普通成员函数中调用静态成员函数
38 }
39 void Student::show2(){ //编译器不会为静态成员函数添加this指针 
40     cout<<"调用了方法show2"<<endl;
41     //cout<<"Name:"<<Name<<endl; //错误:静态成员函数不能访问非静态数据成员 
42     //cout<<"Age:"<<Age<<endl; //错误:静态成员函数不能访问非静态数据成员
43     //show1(); //错误:静态成员函数中不能调用普通成员函数 (只能以this->show1()的形式调用)
44     cout<<"Count:"<<count<<endl;
45 }
46 int main(){
47     Student stu1("Tomwenxing",23);
48     Student stu2("Ellen",22);
49     Student stu3("Jack",24);
50     stu3.show1();
51     cout<<"----------分界线----------------"<<endl; 
52     stu2.show2();//可以通过对象来调用静态成员函数 
53     cout<<"----------分界线----------------"<<endl; 
54     Student::show2() ;//也可以通过类来调用静态成员函数 
55     return 0;
56 }

原文地址:https://www.cnblogs.com/duwenxing/p/7465372.html