在C语言中,关键字static的意思是静态,它主要有如下两个作用:
(1)在函数体内,静态变量具有“记忆”功能,即一个被声明为静态的变量只会被初始化一次,然后在这一函数被调用的过程中其值维持不变。
(2)在文件内(但在函数体外),用来限制变量或函数的作用域为当前文件,即如果一个变量被声明为静态的,那么该变量可以被当前文件内所有函数访问,但不能被其他文件中的函数访问。它是一个本地的全局变量,且只会被初始化一次。如果一个函数被声明为静态的,那么该函数与普通函数作用域不同,其作用域仅在本文件中,它只可被当前文件内的其他函数调用,不能被其他文件的函数调用。也就是说,这个函数被限制在仅能被声明它的文件内使用。
在C++语言中,除了以上功能外,在类内数据成员的也可以被定义为static,在这种情况下,该数据成员就是类的静态数据成员。
静态数据成员有以下特点:
(1)对于非静态数据成员而言,每个对象都有自己单独的一个副本。而静态数据成员被当作是类的成员,只会存在唯一的副本,且被所有对象共享。
(2)静态成员变量属于类而不属于对象。也就是说,即使没有实例化的对象,也可以使用静态变量,通常通过“类名:静态成员变量”来访问。
(3)静态数据成员和普通数据成员一样遵从public、protected、private访问规则。
(4)static成员变量的初始化是在类外,初始化的时候不需要再使用static关键字。被private或protected修饰的static成员虽然可以在类外初始化,但是不能在类外被访问。
(5)在类中,被static修饰的函数是类的静态成员函数,静态成员函数也属于类,而不属于某一个特定对象,被所有对象共享。普通成员函数一般都隐含了一个this指针,this指针指向类的对象本身,例如,可以通过this->fn( )来调用普通成员函数fn( )。但是,由于静态成员函数属于类,而不属于对象,因此它没有this指针。从这个意义上讲,类的静态成员函数无法访问对象成员,也无法访问普通成员函数,它只能访问静态成员函数或静态成员。也就是说,静态成员函数不能直接或间接地访问非static函数或成员变量。
与全局变量相比,使用静态数据成员有以下两个优势:
(1)全局变量的作用范围是整个工程,而static变量的作用范围仅仅是这个变量所在的文件。static变量与全局变量相比,减少了命名冲突的可能性。可以在不同的文件中定义名字相同的static变量,但是不能定义名字相同的全局变量。
(2)可以实现信息隐藏。静态数据成员可以是private成员,而全局变量不能。需要注意的是,类的静态成员必须被初始化,而且必须在类外面初始化。为什么静态变量不能在类内部初始化呢?由于类的声明可能会被多个地方引用,如果把静态变量的初始化放在类内部,每次引用都会初始化一次(分配一次空间),这与静态变量只能初始化一次且只存在一个副本相冲突,因此,静态变量只能在类外面初始化。
引申1:在C语言中,为什么static变量只初始化一次
答案:对于所有的对象(不仅仅是静态对象),初始化都只有一次,而由于静态变量具有“记忆”功能,初始化后,一直都没有被销毁,都会保存在内存区域中,所以不会再次初始化。存放在静态区的变量的生命周期一般比较长,它与整个程序“同生死、共存亡”,所以它只需初始化一次。而auto变量,即自动变量,由于它存放在栈区,一旦函数调用结束,就会立刻被销毁。分析以下程序代码:[插图]第一次调用fun(0)的时候,value被初始化为0,执行value+=i后,value的值还是0;接着在调用f(1)的时候,由于value是static变量,因此初始化语句static int value=0不再被执行,而直接执行value+=i。由于此时value=0,i=1,执行结束后,value的值变为1。最后在调用f(2)的时候,value=1,i=2,因此执行结束后,value的值变为3。
引申2:在头文件中定义静态变量是否可行,为什么
答案:不可行,如果在头文件中定义静态变量,会造成资源浪费的问题,同时也可能引起程序错误。因为如果在使用了该头文件的每个C语言文件中定义静态变量,按照编译的步骤,在每个头文件中都会单独存在一个静态变量,从而会引起空间浪费或者程序错误。所以,不推荐在头文件中定义任何变量,当然也包括静态变量。