C++基础专栏:http://t.csdnimg.cn/4FdOH
目录
1.引言
在面试的过程,面试官经常都会问到static关键字有哪些用法?在C/C++中各有些什么作用?今天就在这里我们好好的总结一下static的全方位用法。
2.静态局部变量
局部变量也就是定义在函数内部的变量,函数局部变量存放在栈区,该变量的生命周期由所在 {} 决定,进入 {} 作用范围而分配内存空间,退出 {} 作用范围而释放内存空间。在局部变量的前面加上static,变成静态局部变量,即使多次调用该函数,静态变量的空间也只分配一次。
定义在函数体内的变量加上static修饰符,它的存在意义是随着第一次函数的调用而初始化,但却不随着函数的调用结束而销毁。因此静态局部变量保存在全局数据区,而不是保存在栈中,每次的值保持到下一次调用,直到下次赋新值。
示例如下:
- #include
- using namespace std;
-
- void test(void)
- {
- int a = 1; // 局部变量
- static int b = 10; //静态局部变量
-
- a++;
- b++;
- cout << "a:" << a << ", b: " << b << endl;
- }
- int main()
- {
- test(); //输出: a=1,b=11
- test(); //输出: a=1,b=12
- test(); //输出: a=1,b=13
- test(); //输出: a=1,b=14
- return 0;
- }
3.静态全局变量
全局变量的空间会在程序的生命周期内分配,在全局变量的前面加上static,变成静态全局变量。
静态全局变量在全局数据区分配内存,那它和全局变量有啥区别呢?
全局变量不但在本文件中可以被访问,在其他文件中同样可以访问。写代码时很容易在不同文件定义相同名字的全局变量,这就会引发冲突。而静态全局变量只能在声明它的整个文件可见,限制了该变量的访问范围。同样的,静态全局函数,在全局函数前加上static,表示只能在声明文件中被访问。
示例:变量g_nTotalCount在static.cpp
中定义为静态全局变量,因此无法在main.cpp
中使用,运行会提示 “无法解析的外部符号”。
- //static.pp
- #include
- #include "static.h"
- using namespace std;
-
- static int g_nTotalCount = 22222; //静态全局变量,要想在main.cpp中使用,需定义为全局变量
- //int g_nTotalCount = 22222;
- void func(void)
- {
- int x= 11;
- cout << "x:" << x << endl;
- }
- //static.h
- #include
-
- void func(void);
- //main.cpp
- #include
- #include "static.h"
- using namespace std;
-
- int b = 2425; //全局变量
-
- int main()
- {
- extern int g_nTotalCount; //申明静态全局变量,运行失败,想用g_nTotalCount,则g_nTotalCount需定义为全局变量,而不是静态全局变量
-
- cout << "g_nTotalCount: " << g_nTotalCount << endl;
-
- func();
-
- return 0;
- }
想使用static.cpp
中的全局变量g_nTotalCount
,则需要定义为全局变量,而不是静态全局变量。
4.静态函数
在普通函数定义前加上修饰符static就是静态函数,作用和静态全局变量类似;函数的定义和生命在默认状态下都是extern的,但静态函数只是在申明他的文件当中可见,不能被其余文件所用。
5.静态成员变量
一个类可以定义多个对象,每个对象都会对类中的普通成员变量进行空间分配,这些变量只由它所在对象使用。
静态成员变量是该类的所有对象所共有的。对于普通成员变量,每个类对象都有自己的一份拷贝,而静态成员变量整个类就一份,静态成员变量只分配一次内存,类的所有对象都共享这个变量,不属于任何一个类,不需要对象就可以访问。
静态成员变量不属于特定的对象,不会占用对象的内存,必须在类的外面进行初始化。对象的内存中只包括普通成员变量,注意不包括任何成员函数。sizeof(类名) 不会计算静态成员变量和成员函数。
普通成员变量随这对象的产生而产生,静态成员变量随着类的产生而产生,所以静态成员变量不能由构造函数初始化,即使没有对象,也可以访问静态全局变量。
示例如下:
- #include
- #include
- using namespace std;
-
- class MyTest
- {
- public:
- static int m_x; //声明静态成员变量
- };
- int MyTest::m_x = 3242234; //定义并初始化静态成员变量
-
- int main()
- {
- printf("m_x:%d, sizeof(MyTest):%d\n", MyTest::m_x, sizeof(m_x));
- return 0;
- }
-
- //输出:m_x:3242234
- sizeof(MyTest)=1
6.静态成员函数
就像类中的静态成员变量一样,静态成员函数也不依赖于类的对象,不具体作用于某个对象。
普通成员函数参数自带一个this指针,this指针指向类的对象本身,因为普通成员函数总是属于类对象,当函数被调用时,系统会把当前对象的起始地址赋给 this 指针。
静态成员函数属于类本身,因此不具有this指针。它无法访问属于类对象的非静态成员变量和非静态成员函数,它只能访问其他静态成员变量和静态成员函数。
可以通过对象来调用,但还是建议使 类名::静态成员函数 调用静态成员函数。
静态成员函数和静态成员变量在类实例化之前就已经存在可以访问,而此时非静态成员还是不存在的,因此静态成员函数不能访问非静态成员变量。
示例如下:
- #include
- using namespace std;
-
- class A
- {
- public:
- static int a; //类的静态成员变量
- static int get_a();//类的静态成员函数
-
- int b;
- int get_b();
- };
- int A::a = 100; //静态成员变量可以在类的外部直接定义
- //int A::b = 1000; //普通成员变量在类的外部定义失败
-
- int A::get_a()
- {
- return a; //类的静态成员函数只能访问类的静态成员变量
- //return b + a; //静态成员函数无法调用普通成员变量
- }
- int A::get_b()
- {
- return b + a;//普通成员函数可以调用静态成员变量
- }
-
- int main(void)
- {
- cout << "a: " << A::get_a() << endl; //不需要类的实例,也可以调用类的静态成员函数
-
- A m;
- m.b = 90;
- m.a = 100000;
-
- cout << m.get_a() << endl;
- cout << m.get_b() << endl;
- cout << m.a << endl;
-
- return 0;
-
- }
7.总结
在使用关键字static
的时候,我们需要注意一下几个原则:
-
被
static
修饰的变量的存储位置都在静态区,且生命周期延长至整个程序运行结束。 -
static
具有隔离作用,被static修饰的全局变量和全局函数的作用域由全局变为当前文件。 -
静态变量虽然具有全局变量的生命周期,但只能作用于自己的作用域。
-
普通静态成员需要在类的外面进行初始化。
-
静态成员函数不能调用类的非静态成员,包括非静态成员和非静态成员函数。
评论记录:
回复评论: