与static相对的关键字是auto,两者是一对。我们一般声明变量,如:int a,其实都是auto int a,只是auto省略了而已,但是static不能省略。要理解static,最好先理解auto。auto的含义是由程序自动控制变量的生存周期,通常是变量在进入其作用域的时候被分配,离开其作用域的时候被释放;而static则不同,变量在程序初始化时被分配,直到程序退出前才被释放;也就是static是按照程序的生命周期来分配释放变量的,而不是按照变量自己的生命周期。
如:
void func() { int a; static int b; }就算函数结束了,b的值也能够一直保持。每一次调用该函数,变量a都是新的,因为它是在进入函数体的时候被分配,退出函数体的时候被释放,所以多个线程调用该函数,都会拥有各自独立的变量a,因为它总是要被重新分配的;而变量b不管你是否使用该函数,在程序初始化时就被分配的了,或者在第一次执行到它的声明的时候分配(不同的编译器可能不同),所以多个线程调用该函数的时候,总是访问同一个变量b,这也是在多线程编程中必须注意的!
一般情况下,对于局部变量是存放在栈区的,并且局部变量的生命周期在该语句块执行结束时便结束了。但是如果用static进行修饰的话,该变量便存放在静态数据区,其生命周期一直持续到整个程序执行结束。但是在这里要注意的是,虽然用static对局部变量进行修饰过后,其生命周期以及存储空间发生了变化,但是其作用域并没有改变,其仍然是一个局部变量,作用域仅限于该语句块。
class A
{
PRivate:
static int s_value;
};
类的静态成员必须初始化才能使用,道因为它是在程序初始化的时候分配的,所以必须有初始化,类中只是声明,在cpp中才是初始化,静态成员初始化与一般数据成员初始化不同。静态数据成员初始化的格式如下:
int A::s_value = 0;//<数据类型><类名>::<静态数据成员名>=<值>,注意,这里没有static的修饰!
使用静态成员时,可以通过双冒号(即<类名>::<静态成员名>)。
类的静态成员是该类所有实例的共用成员,也就是在该类的范畴内是个全局变量,也可以理解为是一个名为A::s_value的全局变量,只不过它是带有类安全属性的。道理很简单,因为它是在程序初始化的时候分配的,所以只分配一次,所以就是共用的。
class A
{
private:
void init();
static void output();
};
void main() {A::init();A::output(); }//A::init();会出错,因为不能通过类名来调用类的非静态成员函数。
void main() {A pt;pt.init();pt.output(); }//编译通过,因为类的对象可以使用静态成员函数和非静态成员函数。
静态成员函数和静态数据成员一样,它们都属于类的静态成员,不是对象成员。因此,对静态成员的引用不需要用对象名,当然,通过对象来使用也可以。在静态成员函数的实现中不能直接引用类的非静态成员,可以引用类中的静态成员。如果静态成员函数中要引用非静态成员时,可通过对象来引用。因为静态成员函数属于整个类,在类实例化对象之前就已经分配空间了,而类的非静态成员必须在类实例化对象后才有内存空间,所以调用就会出错,就好比没有声明一个变量却提前使用它一样。
实现的时候也不需要static的修饰,因为static是声明性关键字;类的静态函数是在该类的范畴内的全局函数,实际上,它就是增加了类的访问权限的全局函数:void A::output();
注意:静态成员函数可以继承和覆盖,但无法是虚函数;在类的非静态成员函数中可以使用类的静态成员。
若在cpp中有,static int g_value = 0;
这个变量的含义是在该cpp内有效,其他的cpp文件不能访问这个变量;如果有两个cpp文件声明了同名的全局静态变量,那么他们实际上是独立的两个变量;如果不使用static声明全局变量:int g_value = 0;那么将无法保证这个变量不被别的cpp共享,也无法保证一定能被别的cpp共享。
如果在一个h文件中声明:static int g_vaule = 0;
那么会为每个包含该头文件的cpp都创建一个全局变量,但他们都是独立的;所以也不建议这样的写法,因为只是创建了一组同名而不同作用域的变量;
在cpp内声明: static void func();
函数的实现不需要static修饰,那么这个函数只可在本cpp内使用,不会同其他cpp中的同名函数引起冲突;不要在头文件中声明static的全局函数,不要在cpp内声明非static的全局函数,如果你要在多个cpp中复用该函数,就把它的声明提到头文件里去,否则在cpp内部声明需要加上static修饰;在C语言中这点尤为重要!
在C语言中,修饰符extern用在变量或者函数的声明前,用来说明“此变量/函数是在别处定义的,要在此处引用”。在这里要注意extern声明的位置对其作用域也有关系,如果是在main函数中进行声明的,则只能在main函数中调用,在其它函数中不能调用。其实要调用其它文件中的函数和变量,只需把该文件用#include包含进来即可,为啥要用extern?因为用extern会加速程序的编译过程,这样能节省时间。
在头文件里声明为extern的:extern int g_value; // 注意,不要初始化值!
然后在其中任何一个包含该头文件的cpp中初始化(一次)就好:
int g_value = 0; // 初始化一样不要extern修饰,因为extern也是声明性关键字;
然后所有包含该头文件的cpp文件都可以用g_value这个名字访问相同的一个变量。
新闻热点
疑难解答
图片精选