static的使用
一些使用技巧
- static声明的变量用于延长变量的声明周期, static的使用目的:局部变量不想被释放的时候,可以使用static修饰
- 尽量少定义静态方法和属性,除非是用作为公用资源的目的来使用
- 文件中的函数设置为static的目的:是限制访问域 - 只有本地文件能访问,但静态函数也尽量少用
static 与 底层
- static 修饰的变量会被定义在全局(静态)存储区,这个区又分为DATA段和BSS段,且程序结束时自动释放。
- DATA段:存放初始化的全局变量和静态变量
- BSS段:存放未初始化的全局变量和静态变量,在程序执行之前会被系统自动置零,所以才有static 变量会被系统自动初始化为0的特性。
- 静态数据成员按定义出现的先后顺序依次初始化,而消除则是反顺序的。
因为静态成员要在程序一开始运行时就必须存在,需要实际地分配空间,所以不能在类的声明中定义(这就是下面说的static成员变量要在source文件中类外初始化),这是由于类的声明只是声明类的“尺寸和规格”,而并不进行实际的内存分配,所以类的声明中定义是错误的(一般类的声明都在header中且header会被多个source 引用,所以如果在header的类外进行初始化,会存在重复定义的问题)。
扩展知识: 一般程序把新产生的动态数据存放在堆区,函数内部的自动变量存放在栈区–因为函数调用是用栈管理的。
完成程序内存分配情况:
- 代码区 //low address
- 全局数据区
- 堆区
- 栈区 //high address
static修饰函数
- static的函数-静态函数:和修饰全局变量类似特性,只能在本文件中被访问;有的编码规范要求只本文件使用的函数用static修饰。
- 一般尽量少定义静态函数,因为静态传染?
static 修饰局部变量
- 在普通函数中声明static 变量的唯一目的是:想将函数中此变量的值保存至下一次调用而不用全局变量(有限选择静态变量,这样跟的函数走而不至于被其他地方误用 - 保留函数的封装性),只被初始化一次。【它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束。】
static修饰全局变量
- static的全局变量:这个static的全局变量只能在本文件中被访问,不能在其它文件中访问,即便是 extern 外部声明也不可以。【注意是static全局变量的意思是不在任何函数和类中的】
- 对比普通全局变量:全局变量默认是有外部链接性的,作用域是整个工程,在一个文件内定义的全局变量,在另一个文件中,通过 extern 全局变量名的声明,就可以使用全局变量
- static 变量在编译的过程中会被自动初始化为0:static的变量一般初始化时会自动初始化为0,但是一般在声明处初始化
static 修饰类的成员
- 在类中定义static的成员变量目的: 需要一个数据为整个类服务,而不是为某个实例化对象服务,且不破坏类的封装性,这就要求类中定义static成员变量;当所有对象都公用一些东西的时候,考虑将其声明为static类型
- 类中static成员变量的初始化:一般建议来类外显性初始化,并且放到源文件中。
// 类的static 变量
// in header file
class TestClass {
public:
static int member; // 类内声明
};
// in source file
int Person::member = 10; // 类外初始化
- 静态成员的定义或声明要加个关键 static
- 通过双冒号来使用,<类>::<静态成员>
- 静态方法只能修改静态成员变量和静态方法, 但是非静态的方法可以调用静态方法和静态成员变量(因为非公用的可以用公用的,但是公用的不能访问非公用的–即对象方法)
- 为什么要尽量少用净态函数呢?
- 测试困难:静态方法将使用静态属性,并且由于它们正在使用静态属性,在独立的单元测试中,容易造成问题,所以测试不方便。
- 不灵活:对于面向对象编程,核心是依赖抽象也就是通过实现接口来抽象对象的调用;1)如果用静态方法则没有抽象的特性,如果需求改变需要其他静态函数,则调用方也需要改变。2)静态方法无法被重新定义【所以有人会说static是反设计模式的】
- 静态传染:如果一个静态方法 A 需要调用另一个方法 B,那么 B 也必须是静态的,这就是静态传染,会引入不必要的麻烦。
- 为了节省内存释放GC压力,也需要少定义些静态属性和方法。