普通的成员变量存放在栈中,当在函数结束后栈内存被释放,如果想有一个变量,在函数结束后仍然被保留。可采用static修饰。
全局/static存储区:分为DATA 段和 BSS 段,DATA 段(全局初始化区)存放初始化的全局变量和静态变量。BSS 段(全局未初始化区)存放未初始化的全局变量和静态变量。程序运行结束时自动释放。其中BBS段在程序执行之前会被系统自动清0,所以未初始化的全局变量和静态变量在程序执行之前已经为0。。
存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。
静态数据成员不能在任何函数内分配空间和初始化。需要在类外初始化。
static 被引入以告知编译器,将变量存储在程序的静态存储区而非栈上空间,
优势:可以节省内存,因为它是所有对象所公有的,因此,对多个对象来说,静态数据成员只存储一处,供所有对象共用。静态数据成员的值对每个对象都是一样,但它的值是可以更新的。只要对静态数据成员的值更新一次,保证所有对象存取更新后的相同的值,这样可以提高时间效率。
什么时候用static:需要一个数据对象为整个类而非某个对象服务,同时又力求不破坏类的封装性,即要求此成员隐藏在类的内部,对外不可见。
静态成员需要定义,在类外定义,类内声明。定义时才分配内存。
静态成员在类外定义和初始化是保证static成员变量只被定义一次的好方法。
static 修饰的静态局部变量只执行初始化一次,而且存放在全局变量,声明周期与程序相同。
static 修饰的全局变量只能在本文件中访问,不能在其它文件中访问,即便是 extern 外部声明也不可以。
static 修饰的函数只能在本文件中调用,不能被其他文件调用。static 修饰的变量存放在全局数据区的静态变量区,包括全局静态变量和局部静态变量,都在全局数据区分配内存。初始化的时候自动初始化为 0。
不想被释放的时候,可以使用static修饰。比如修饰函数中存放在栈空间的数组。如果不想让这个数组在函数调用结束释放可以使用 static 修饰。
如果有一 变量不想随函数的结束而释放,可以用static修饰
静态全局变量和静态局部变量都存放在全局区。
静态变量会被默认初始化为0,类内的普通变量是被随机初始化的。除非显示赋值初始化。
用static修饰的优点:静态全局变量不能被其它文件所用;其它文件中可以定义相同名字的变量,不会发生冲突。
全局变量和全局静态变量的区别:
全局变量是不显式用 static 修饰的全局变量,全局变量默认是有外部链接性的,作用域是整个工程,在一个文件内定义的全局变量,在另一个文件中,通过 extern 全局变量名的声明,就可以使用全局变量。
全局静态变量是显式用 static 修饰的全局变量,作用域是声明此变量所在的文件,其他的文件即使用 extern 声明也不能使用。
被 static 修饰的变量属于类变量,可以通过类名.变量名直接引用,
被static修饰的静态成员 变量、静态成员函数属于类的静态资源,类的实例之间共享一个静态成员,换言之,一处变、处处变。静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供所有对象共用。。可以通过类名.变量名直接引用。
不能通过类名来调用类的非静态成员函数。
类的对象可以使用静态成员函数和非静态成员函数。
静态成员函数中不能引用非静态成员。
类的非静态成员函数可以调用用静态成员函数,但反之不能。
静态成员函数和静态数据成员一样,他们都属于类的静态成员,而不是对象成员
非静态成员函数有 this 指针,而静态成员函数没有 this 指针。
类内:
static类对象必须要在类外进行初始化,static修饰的变量先于对
象存在,所以static修饰的变量要在类外初始化;
由于static修饰的类成员属于类,不属于对象,因此static类成员
函数是没有this指针的,this指针是指向本对象的指针。正因为没有this
指针,所以static类成员函数不能访问非static的类成员,只能访问
static修饰的类成员;
static成员函数不能被virtual修饰,static成员不属于任何对象或
实例,所以加上virtual没有任何实际意义;静态成员函数没有this指
针,虚函数的实现是为每一个对象分配一个vptr指针,而vptr是通过
this指针调用的,所以不能为virtual;
虚函数的调用关系,this->vptr->ctable->virtual function
二、static静态变量的初始化
static静态变量初始化只有一次,但是可以多次赋值,在主程序之
前,编译器已经为其分配好了内存。
静态局部变量和全局变量一样,数据都存放在全局区域,所以在主
程序之前,编译器已经为其分配好了内存,但在C和C++中静态局部变
量的初始化节点又有点不太一样。
在C中,初始化发生在代码执行之前,编译阶段分配好内存之后,
就会进行初始化,所以我们看到在C语言中无法使用变量对静态局部变
量进行初始化,序运行结束,变量所处的全局内存会被全部回收。
而在C++中,初始化时在执行相关代码时才会进行初始化,主要是
由于C++引入对象后,要进行初始化必须执行相应构造函数和析构函
数,在构造函数或析构函数中经常会需要进行某些程序中需要进行的特
定操作,并非简单地分配内存。所以C++标准定为全局或静态对象是有
首次用到时才会进行构造,并通过atexit()来管理。在程序结束,按照构
造顺序反方向进行逐个析构。所以在C++中是可以使用变量对静态局部
变量进行初始化的。