1. 面向过程设计的static
1.1. 静态全局变量
全局变量加上static称为静态全局变量:
- 静态全局变量在全局数据区分配内存
- 未经初始化的静态变量会被程序自动初始化为0
- 静态全局变量在声明它的整个文件中都是可见的,文件之外不可见(非静态全局变量整个源程序都可见)
1.2. 静态局部变量
局部变量加上static称为静态局部变量。通常函数体内定义一个变量,每当程序运行到该语句时都会给局部变量分配栈内存,随着程序退出函数体,系统就会回收栈内存,局部变量相应失效。
但若需要两次调用之间对变量的值进行保存,通常可以定义一个全局变量,但这样变量不再属于函数本身,不再仅受函数控制,程序维护不便。
静态局部变量的特点:
- 该变量在全局数据区分配内存
- 静态局部变量在程序执行到该对象处时首次初始化,之后对函数的调用不再进行初始化过程
- 静态局部变量一般在声明处初始化
- 始终驻留在全局数据区,知道程序运行结束,但是其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随着结束
- 可以进行二次赋值操作
1.3. 静态函数
静态函数就是函数前加static,静态函数不能被其他文件所用,可以避免定义相同名字的函数使发生冲突.
2. 面向对象中的static
2.1 静态数据成员
对于非静态数据成员,每个类对象都有自己的拷贝,而静态数据成员被当作是类的成员,无论这个类的对象被定义了多少个,静态数据成员在程序中只有一份拷贝,由该类型的所有对象共享访问。也就是说,静态数据成员是该类的所有对象所共有的,对该类的多个对象来说,静态数据成员只分配一次内存,供所有对象公用。所以静态数据成员的值对每个对象都是一样的,它的值可以更新。
静态数据成员存储在全局数据区,定义时分配空间,所以不能再类声明中定义。
2.2. 静态成员函数
与静态数据成员一样,静态成员函数为类的全部对象服务而不是某一个类的具体对象。他们都属于类定义的一部分。普通的成员函数一般都隐含了this指针,this指针指向类的对象本身,通常情况下,这个指针是缺省的。但是静态成员函数不与任何对象相联系,所以不具有this指针。也就是说,静态成员函数不能访问属于类对象的非静态数据成员/成员函数,它只能调用静态成员函数。
2.3. 其他
静态数据成员要在程序一开始运行时就必须存在,因为函数在程序运行中被调用,所以静态数据成员不能在任何函数内分配空间和初始化。
这样的它的空间分配有三个可能的地方,一是作为类的外部接口的头文件(那里有类声明);二是类定义的内部实现(那里有类的成员函数定义);三是应用程序的main函数前的全局数据声明和定义处。
静态数据成员要实际地分配空间,故不能在类的声明中定义(类声明知识声明一个类的尺寸和规格并不进行实际的内存分配)。也不能在头文件中类声明的外部定义(会造成多个使用该类的源文件中对其重复定义)。static被引入以告知编译器将变量存储在程序的静态存储区而非栈上空间。
此外:
- 不能将静态成员函数定义为虚函数
- 静态数据成员是静态存储的必须初始化
- 为了防止父类的影响,可以在子类中定义一个与父类相同的静态变量,以屏蔽其影响。静态成员为父类和子类共享,但重复定义了静态成员不会引起错误,这是因为编译器采用了name-mangling用于生成唯一的标志。
Name-mangling是指为了在目标文件符号表中和连接过程中使用的名字通常和编译目标文件的源程序中的名字不一样,编译器将目标源文件中的名字进行调整
欢迎扫描二维码关注微信公众号 深度学习与数学 [每天获取免费的大数据、AI等相关的学习资源、经典和最新的深度学习相关的论文研读,算法和其他互联网技能的学习,概率论、线性代数等高等数学知识的回顾]