“ 一个人追求的目标越高,他的才力就发展的越快,对社会就越有益。”
我们知道C++有三种管理数据内存的方式:自动存储、静态存储和动态存储。
自动存储:在函数内部定义的常规常量使用动态存储,即局部变量,在所属函数被调用时自动产生,在该函数结束时消亡。存储区域为栈。
静态存储:是整个程序执行期间都存在的存储方式。使变量成为静态的方式有两种:一种是全局变量,另一种就是用static关键字修饰的变量。
动态存储:使用new和delete管理的内存池,存储在堆上。
存储类别影响信息在文件间的共享,自动存储和动态存储之前已经讨论了很多了,我们今天主要总结一下静态存储,方便以后查用。
0. static关键字用法总结
一直对static关键字的使用概念很模糊,模棱两可,不太敢用,也不知道什么地方该用。其实static用法非常广泛,修饰静态变量(局部变量和全局变量)、静态函数、静态成员(成员变量和成员函数)等,如果用的好,会使程序提升一个等级,并且可以解决很多实际问题,比如单例模式…而且静态数据成员存储在静态存储区,只存储一次,可以节省内存。
对于非成员变量和函数来说,static关键字起隐藏作用
static修饰的变量为静态变量,分为静态全局变量和静态局部变量。具有以下特性:
静态变量的存储区域为全局存储区,内存分配在.data段,在链接阶段进行符号解析时不做处理
静态变量只初始化一次,未初始化的静态变量会默认初始化为0
静态变量的生命周期为整个程序的运行期间
静态全局变量只在本文件内可见,外部无法通过extern关键字访问到,除非其他文件包含该全局变量声明的头文件
静态局部变量只在定义的作用域内可见
static修饰的函数为静态函数,主要起到函数隐藏的作用,作用域为当前文件,在其他文件中无法找到该函数的地址。
static修饰类的成员变量和成员方法
static修饰的成员变量具有如下特性:
static修饰的数据成员属于类的组成部分,static修饰的数据成员不在栈上分配内存而在.data段分配内存
可供所有的对象访问,只分配一次内存,也只有一份拷贝,对于每个对象都是一样,它的值可以更新
不能通过构造函数来进行初始化,因为是在类产生的时候分配的内存,产生于对象之前,因此static修饰的数据成员必须在类外进行初始化且只会初始化一次。初始化的方法为::=
通过对象或者类名都可以访问
class Example{public: static int count; Example() { count++; }};int Example::count = 0;int main(){ Example e1,e2; cout<<:count>}
static修饰的成员变量具有如下特性:
与静态成员类似,它是类内部共同享用
静态成员函数没有this指针,非静态成员函数可以访问静态成员与静态函数,但是静态成员函数不能直接调用非静态成员,只能调用静态成员
static成员不是任何对象的组成,不依赖对象的调用所以static成员方法不能被声明为const,因为const只限定该类的对象
static成员方法不能同时被声明为虚函数
静态成员函数可以在没有对象的情况下直接通过类名进行调用,也可以通过对象进行调用
1. 静态存储的链接性
作用域描述名称在文件的多大范围内可见,而链接性则描述名称如何在不同单元间共享。外部链接性指在文件间共享,例如全局变量;内部链接性指在一个文件内的函数间共享,例如静态全局变量;无链接性指不能共享,例如局部变量(普通的局部变量和static修饰的局部变量)。可见静态变量具有以上三种链接性。
如下代码中,尽管global、oneFile、count都在程序运行期间存在,但是count没有链接性,只能在func1函数内使用它。global和oneFile的作用域都为整个文件,但是global的链接性为外部的,意味着在程序的其他文件中也是可见的;oneFile的链接性为内部的,只能在包含oneFile所在代码的文件中使用。
// main.cppint global = 1000;static int oneFile = 0;int main(){ ... ...}void func1(int n){ static int count = 0;}
C++的“单定义规则”只出:变量只能定义一次。为满足这种需求,C++提供了两种变量声明。一种是定义声明,它为变量分配拟存储空间;另一种是引用声明,不分配存储空间,使用关键字extern,且不进行初始化。
静态局部变量无链接性,只在代码块中可用。只在启动的时候初始化一次,以后再调用代码块时,将不会被再次初始化。
全局const定义的变量的链接性为内部的。
// main.cppconst int num = 0; // 链接性为内部int main(){ ... ...}
static关键字如果用好了可以使我们的代码上升一个层次,但是这块的东西又特别的杂乱,希望这次总结能帮助大家理清思绪。