主要参考:C/C++ 中 static 的用法全局变量与局部变量
其他参考:C 语言中 static 的作用
静态变量
静态变量的作用:限定此变量的使用范围,并在限定访问内共享此变量,具体如下:
- 函数内定义的静态变量:对函数内定义的静态变量的修改会保存到下一次调用,并且此静态变量只属于本函数
- 类中的成员变量定义为静态变量:类中的成员变量定义为静态变量,此变量为类变量,被全体对象所共享。
- static 修饰全局变量的时候,这个全局变量只能在本文件中访问,不能在其它文件中访问,即便是 extern 外部声明也不可以。
全局(静态)存储区:分为 DATA 段和 BSS 段。
- DATA 段(全局初始化区)存放初始化的全局变量和静态变量,根据设定的值初始化。
- BSS 段(全局未初始化区)存放未初始化的全局变量和静态变量,程序执行之前会被系统自动清0。
存储在静态数据区的变量会在程序运行前就完成初始化,也是唯一的一次初始化(如果再次进行了初始化将会被忽略)。所以不管是在类内、函数内或者其他地方定义的静态变量都是在程序运行前就分配空间和初始化。
下面对上面的一些结论进行举例说明:
说明1:
函数内定义的静态变量:对函数内定义的静态变量的修改会保存到下一次调用,并且此静态变量只属于本函数。举例如下:
#include <stdio.h>
int fun(void){
static int count=10; // 事实上此赋值语句从来没有执行过
return --count;
}
int fun2(){
static int count=-5; // 事实上此赋值语句从来没有执行过
return --count;
}
static int count = 1;
int main(void)
{
printf("%d\n", fun());
printf("%d\n", fun2());
printf("%d\n", fun());
printf("%d\n", fun2());
return 0;
}
输出:
9
-6
8
-7
说明2:
存储在静态数据区的变量会在程序运行前就完成初始化,也是唯一的一次初始化(如果再次进行了初始化将会被忽略)。举例如下:
#include <stdio.h>
int fun(void){
static int count=10; // 只在运行前进行初始化操作,再次进行了初始化将会被忽略。
// 也就是说此段赋值代码在运行期间没有被执行过。
return count--;
}
int count = 1;
int main(void)
{
printf("global\t\tlocal static\n");
for(int i=0; i <= 10; ++i)
printf("%d\t\t%d\n", count, fun());
return 0;
}
其他:
- 考虑到数据安全性(当程序想要使用全局变量的时候应该先考虑使用 static)。
静态函数
全局的静态函数只能在本文件中使用。
静态成员函数:
- 不能通过类名来调用类的非静态成员函数。
- 静态成员函数中不能引用非静态成员,因为静态成员函数属于整个类,在类实例化对象之前就已经分配空间了,而类的非静态成员必须在类实例化对象后才有内存空间,所以这个调用就出错了,就好比没有声明一个变量却提前使用它一样。
- 非静态成员函数可以调用用静态成员函数,但反之不能。
- 非静态成员函数有隐含this 指针作为形参,而静态成员函数没有隐含this 指针。
两个注意点
【注意点一】:记得定义静态成员变量
#include <stdio.h>
class Point
{
public:
Point()
{
m_nPointCount++;
}
~Point()
{
m_nPointCount--;
}
static void output()
{
printf("%d\n", m_nPointCount);
}
private:
static int m_nPointCount;
};
void main()
{
Point pt;
pt.output();
}
m_nPointCount只进行了声明没有定义,所以编译的时候会提示m_nPointCount没有定义。
extern、关于C++的变量和类的声明和定义中有提到类中成员变量的声明和定义的相关概念。
【注意点二】静态变量和其他变量的名字不能一样
#include <stdio.h>
int main(void)
{
int count = 1;
static int count=10;
return 0;
}
出现重定义错误。
static修饰类
static 修饰类:static 一般情况下来说是不可以修饰类的, 如果 static 要修饰一个类,说明这个类是一个静态内部类(注意 static 只能修饰一个内部类),也就是匿名内部类。
【注】内部类也就是内部的类,是包含在一个类里面的类