1.全局变量
对全局变量声名static时,static限制其作用域为当前文件,其他文件不可访问,即使声明为extern(表示不同文件共享该变量,同时这也是默认的全局变量的作用范围)。
此外,声明为static的变量会放到全局/静态存储区,即由编译器将变量初始化放在数据段,在程序结束时销毁。
同样的,使用static声名某函数,表明该函数的可见性仅限于当前文件。
2.局部变量
对局部变量声名为static时,同样会将该值放入静态存储区,但是局部变量的作用域仅限于该函数体内(这与全局变量声明为static时仅限于该文件内相似)。
因而函数内的static局部变量仅会初始化一次并放入数据段。看如下例子
#include <iostream>
using namespace std;
static int a;
int* func(){
static int b=0;
cout<<b++<<endl;
return &b;
}
int main(){
func();
int *b = func();
cout<<"a:"<<&a<<endl;
cout<<"b:"<<b<<endl;
return 0;
}
定义了两个static,一个是全局的,一个是函数内的,运行结果如下:
0
1
a:0x4a7034
b:0x4a7038
可以看到func()内的b仅初始化了一次,所以两次运行结果不同。此外分别打印两个static变量的存储位置,可以看到储存位置相近,即都存到了全局数据区。
3.类内成员变量
与上文局部变量相同,类内的成员变量定义为static时,编译器会将其放入全局数据区。类的多个实例访问的实际上是同一个变量地址,因而static定义的成员变量被多个实例共享。
初始化:不进行初始化时编译器会置0(或置空),想要给定初始值时必须在类外声名。且想在类外访问时必须声名,然后可通过 类名::变量 或 对象.变量 进行访问。
#include <iostream>
using namespace std;
static int a;
class A{
public:
static int b;
};
int A::b = 0;
int main(){
A::b = 2;
A a;
a.b = 3;
}
4.类内成员函数
声明为类内成员函数时,该函数不会将this指针作为隐藏参数。
通常来讲,由于共用一套函数,类的成员函数编译后会加入隐藏的this指针变量,这样函数才能对特定对象的成员进行访问。this指针默认通过CX寄存器进行传参。
但当声明为static时,该函数不会有this指针传入,因而不能修改普通成员变量,static成员变量除外(因为其存于全局数据区,不需要this即可访问)
因而: (1)static成员函数仅能访问static成员变量。
(2)static成员函数可以通过 类名::函数名 或 对象.函数名 进行访问。
(3)由于没有隐含的this指针,故用const来限定无法修改成员变量是无意义的,故无法将一个static成员函数声明为const。