1.静态全局变量与全局变量
- 在全局变量前加上 static 关键字,即为静态全局变量;
- 静态全局变量在程序的全局数据区分配内存,若未初始化则默认初始化为 0,直到程序结束才销毁;
- 静态全局变量在该文件内可见,从变量定义处开始直到文件结束 (普通全局变量在同一程序的其他文件中可见,默认是 external 属性,而静态全局变量是 internal 属性), 而在其他文件中不可见。(对外隐藏)
全局变量使用
在一个.cpp 里定义这个变量;
在头文件里 extern 这个变量;
其他引用这个头文件的文件就都可以使用全局变量了;
Note:尽量不用全局变量,换做静态全局变量!!!
2.静态局部变量
通常,在函数体内定义了一个变量,每当程序运行到该语句时都会给该局部变量分配栈内存。但随着程序退出函数体,系统就会收回栈内存,局部变量也相应失效;
静态局部变量特点:
- 该变量在全局数据区分配内存; (改变声明周期,但作用范围不变)
- 静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后函数调用不再进行初始化; (函数中再次调用也不会再赋值)
- 静态局部变量每次的值保持到下一次调用(退出函数,空间不回收),直到下次赋新值或程序运行结束。
void fn()
{
static n=10;
cout<<n<<endl;
n++;
}
3.静态函数
在函数的返回类型前加上 static 关键字,函数即被定义为静态函数。
静态函数与普通函数不同,它只能在声明它的文件当中可见,不能被其它文件使用。(不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名,因为同名也没有关系。 )
static void fn ();// 声明静态函数
void main()
{
fn();
}
void fn ()// 定义静态函数
{
int n=10;
cout<<n<<endl;
}
4.静态成员变量
特点:
- 对于非静态数据成员,每个类对象都有自己的拷贝。而静态数据成员被当作是类的成员。也就是说,静态数据成员是该类的所有对象所共有的。对该类的多个对象来说,静态数据成员只分配一次内存,供所有对象共用。所以,静态数据成员的值对每个对象都是一样的,它的值可以更新;
- 静态数据成员和普通数据成员一样遵从 public,protected,private 访问规则;
- 静态数据成员初始化与一般数据成员初始化不同。静态数据成员初始化的格式为:
<数据类型><类名>::<静态数据成员名>=<值>
- 类的静态数据成员有两种访问形式:
<类对象名>.<静态数据成员名> 或 <类类型名>::<静态数据成员名>
class Myclass
{
public:
Myclass(int a,int b,int c);
void GetSum();
private:
int a,b,c;
static int Sum;// 声明静态数据成员
};
int Myclass::Sum=0;// 定义并初始化静态数据成员
5.静态成员函数
普通的成员函数一般都隐含了一个 this 指针,this 指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。通常情况下,this 是缺省的。如函数 fn () 实际上是 this->fn ()。
但是与普通函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有 this 指针。从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数。
class Myclass
{
public:
Myclass(int a,int b,int c);
static void GetSum ();/ 声明静态成员函数
private:
int a,b,c;
static int Sum;// 声明静态数据成员
};
int Myclass::Sum=0;// 定义并初始化静态数据成员
Myclass::Myclass(int a,int b,int c)
{
this->a=a;
this->b=b;
this->c=c;
Sum+=a+b+c; // 非静态成员函数可以访问静态数据成员
}
void Myclass::GetSum () // 静态成员函数的实现
{
// cout<<a<<endl; // 错误代码,a 是非静态数据成员
cout<<"Sum="<<Sum<<endl;
}
拓展
一个完整的程序,在内存中的分布情况如下图:
代码区
全局数据区
堆区
栈区
一般程序的由 new 产生的动态数据存放在堆区,函数内部的自动变量存放在栈区。
自动变量一般会随着函数的退出而释放空间,静态数据(即使是函数内部的静态局部变量)也存放在全局数据区。全局数据区的数据并不会因为函数的退出而释放空间。