一、static修饰变量与函数
static修饰变量包含了局部变量和全局变量。
一般函数内部的变量放在栈区,但是会随着函数的周期而被释放。由函数内部new产生的动态数据则存放在堆区,静态数据则存放在全局数据区,全局数据区的数据并不会随着函数的退出而是放空间。
(1)static修饰全局变量
static写在全局变量前,该变量就被定义为一个静态全局变量
#include <iostream>
using namespace std;
static int n=3; //定义静态全局变量
void Add()
{
n++;
cout << n << endl;
}
int main()
{
n = 1;
cout << n << endl;
Add();
return 0;
}
运行结果:
由于局部变量就近原则,所以显示的结果是2。
特点
- 该变量在全局数据区分配内存
- 未经初始化的静态全局变量会被程序自动初始化为0,除非它被显示初始化。
- 静态全局变量在声明它的整个文件中都是可见的,在其他文件不可见
(2)static修饰局部变量
static写在局部变量前,该变量就被定义为一个静态局部变量。
#include <iostream>
using namespace std;
void Add()
{
static int n = 1;//定义静态局部变量
cout << n << endl;
++n;
}
int main()
{
Add();
Add();
Add();
return 0;
}
运行结果:
由此可见在函数体内部的定义的静态局部变量,在出函数的作用域时,并不释放,因为是存在全局数据区中。
特点
- 静态局部变量在全局数据区中分配内存。
- 静态局部变量在程序执行到该对象声明处被首次初始化,以后函数的调用不再进行初始化。
- 静态局部变量一般在声明处初始化,如果没有显示初始化,会被程序初始化为0。
- 静态局部变量保存在全局数据区中,它的作用域为局部作用域,当定义它的函数或者语句块结束时,它的作用域随之结束。
(3)static修饰函数
static写在函数前,该函数就被定义为一个静态函数。
静态函数与普通函数不同,只能在声明它的文件当中可见,不能在其他的文件当中使用(和静态全局变量类似),同时其他文件可以定义与此函数一样名字的函数,并不会发生冲突。
二、static修饰类中成员
(1)static修饰数据成员
在类中的成员前加上关键字static,即可成为静态数据成员。
class date
{
public:
date(int year=1900,int month=1,int day=1)
:_year(year)
,_month(month)
,_day(day)
{}
private:
static int _year;
int _month;
int _day;
};
我们发现如上代码会显示出来错误,因为static修饰的类中成员不能被初始化。
由于静态数据成员不属于某一个对象的,它属于所有这个类的对象,也就是说对于该类的所有对象,静态数据成员只分配一次内存,每个对象都可以引用这个静态的数据成员,而非静态数据成员,每一个类对象都有一份自己的拷贝。
特点:
静态数据成员存储在全局数据区。静态数据成员定义时要分配空间,所以不能在类声明中定义。初始化只能在类外进行(上面的代码用构造函数对静态数据成员初始化,这也是不行的。),如果未对静态数据成员初始化,则编译系统默认自动赋值为0。
初始化方式:<数据类型><类名>::<静态数据成员名>=<值>
静态数据成员同样遵守public、protected、private的访问规则。
如果只定义了类,而未定义对象,则类的一般数据成员是不占内存的,但是由于静态数据成员不属于某一个对象,所以静态数据成员是在所有对象之外单独开辟空间。所以只要我们定义了静态数据成员,即使不定义对象,也为静态数据成员在静态数据区数字段开辟空间,可以被引用。
- 静态数据成员可以通过对象名来引用,也可以通过类名来引用。
<类对象名>.<静态数据成员名>
<类类型名>::<静态数据成员名>
(2)static修饰成员函数
在类中的成员函数前加上关键字static,即可成为静态成员函数。
class date
{
public:
date(int year=1900,int month=1,int day=1)
:_month(month)
,_day(day)
{}
static int Day(){}//此处被声明为静态成员函数
public:
static int _year;
int _month;
int _day;
};
同样,静态成员函数也是属于一个类的,并不是属于某一个对象的,它为类全部服务,而不是为了对某一个对象服务,静态成员函数的存在并不是为了服务类的数据成员,而是为了处理静态数据成员。
由于普通成员函数一般都有隐藏的this指针,this指针指向类的对象本身,当我们调用一个对象的成员函数时,系统会把该对象的地址赋值给成员函数的this指针,但是静态成员函数并不属于某一个类对象,所以也就不具备this指针,也就无法访问属于类的非静态数据成员,也无法访问非静态数据成员,只能调用其他的静态成员函数。
特点:
- 出现在函数体外的定义不能指定为关键字static。
- 静态成员可以在类内互相访问,因为他们都属于本类。
- 静态成员函数不能访问非静态成员函数和非静态数据成员。
- 非静态成员函数可以任意的访问静态数据成员和静态成员函数。
- 由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长。