关键字static总结

来源:互联网 发布:dota改键位软件 编辑:程序博客网 时间:2024/05/22 10:06

一、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。

特点

  1. 该变量在全局数据区分配内存
  2. 未经初始化的静态全局变量会被程序自动初始化为0,除非它被显示初始化。
  3. 静态全局变量在声明它的整个文件中都是可见的,在其他文件不可见

(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;}

运行结果:

这里写图片描述

由此可见在函数体内部的定义的静态局部变量,在出函数的作用域时,并不释放,因为是存在全局数据区中。

特点

  1. 静态局部变量在全局数据区中分配内存。
  2. 静态局部变量在程序执行到该对象声明处被首次初始化,以后函数的调用不再进行初始化。
  3. 静态局部变量一般在声明处初始化,如果没有显示初始化,会被程序初始化为0。
  4. 静态局部变量保存在全局数据区中,它的作用域为局部作用域,当定义它的函数或者语句块结束时,它的作用域随之结束。

(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修饰的类中成员不能被初始化。

由于静态数据成员不属于某一个对象的,它属于所有这个类的对象,也就是说对于该类的所有对象,静态数据成员只分配一次内存,每个对象都可以引用这个静态的数据成员,而非静态数据成员,每一个类对象都有一份自己的拷贝。

特点:

  1. 静态数据成员存储在全局数据区。静态数据成员定义时要分配空间,所以不能在类声明中定义。初始化只能在类外进行(上面的代码用构造函数对静态数据成员初始化,这也是不行的。),如果未对静态数据成员初始化,则编译系统默认自动赋值为0。

    初始化方式:<数据类型><类名>::<静态数据成员名>=<值>

  2. 静态数据成员同样遵守public、protected、private的访问规则。

  3. 如果只定义了类,而未定义对象,则类的一般数据成员是不占内存的,但是由于静态数据成员不属于某一个对象,所以静态数据成员是在所有对象之外单独开辟空间。所以只要我们定义了静态数据成员,即使不定义对象,也为静态数据成员在静态数据区数字段开辟空间,可以被引用。

  4. 静态数据成员可以通过对象名来引用,也可以通过类名来引用。

<类对象名>.<静态数据成员名>
<类类型名>::<静态数据成员名>

(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指针,也就无法访问属于类的非静态数据成员,也无法访问非静态数据成员,只能调用其他的静态成员函数

特点:

  1. 出现在函数体外的定义不能指定为关键字static。
  2. 静态成员可以在类内互相访问,因为他们都属于本类。
  3. 静态成员函数不能访问非静态成员函数和非静态数据成员。
  4. 非静态成员函数可以任意的访问静态数据成员和静态成员函数。
  5. 由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长。