详解C++中的extern与static关键字
本章通过问答方式明晰两个关键字及其作用。
Q1:对于int x;
,不加extern关键字他就是个未赋初值的定义,但是如果加了static或者extern都可以表示这仅是一个声明吗?
A:不是的,具体情况如下:
int x;
是一个定义,它为 x 分配了存储空间,但没有显式地初始化。如果 x 是全局变量或静态变量,它会被隐式初始化为0。类内或函数内局部变量是一个随机数,尽量避免这种情况;
extern int x;
是一个声明,它告诉编译器 x 是一个整型变量,但并未为其分配存储空间。你需要在其他地方定义 x。
static int x;
可以是声明或定义,具体取决于上下文。如果它出现在函数内部,那么它是一个定义,并且 x 只能在该函数内部访问。如果它出现在全局范围内,那么它是一个定义,并且 x 只能在当前文件内访问。如果它出现在类内部,那么它是一个声明,并且你需要在类外定义并初始化这个静态成员变量。
Q2:static是可以用来标记本文件作用域的吗?
A: 是的,对于extern关键字,它可以通过extern int x;
说明x在其他文件中已定义,请到其他地方寻找,但如果同时赋值,那么extern关键字的作用就被抵消了,如extern int x = 1
等价于int x = 1;
;
而对于static int x;
说明x仅在本文件中定义,其他文件无法访问。
Q3:为什么类内的static只是一个声明,定义和赋初值都需要在类外实现?
A:
1.根据primer第4版的解释,static局部对象必须遵守[确保不迟于在程序执行流程第一次经过该对象的定义语句时进行初始化]的这一个原则。
2、同时,我们知道类内部的执行顺序并不是按行次序执行的,而是按对象调用执行的
3、以上两者决定了一个问题: 如果在类内定义,那么不建立对象时,静态数据成员无法初始化,或初始化时间太迟。(可能原因之一]
4、再者,静态成员的生命周期是,一经建立便会存在与整个程序的生命周期内。而静态数据成员即属于类、也不属于类的原因便在此,在类内定义,会使其完全成为该类中的成员,也就是说,当建立复数人该类对象时,会再次声明并定义这静态变量的位置,且名字空间和作用域相同下,导致重名问题。(可能原因之二)
5、因此static的成员需要独立于类作定义
Q4:函数内定义的static变量出了函数作用域后还会存在吗?
A:
是的,函数内定义的静态变量在函数执行完毕后仍然存在。静态变量在程序执行期间只被初始化一次,并且它们的生命周期与程序的生命周期相同。这意味着,即使函数执行完毕,静态变量仍然存在,并且在下一次调用该函数时,它们将保留上一次调用时的值。
例如,下面这个函数 count 使用了一个静态变量 x 来记录它被调用的次数:
void count() {
static int x = 0;
x++;
cout << x << endl;
}
每次调用 count 函数时,x 的值都会增加1,并输出当前的值。即使函数执行完毕,x 仍然存在,并且在下一次调用 count 函数时,它将保留上一次调用时的值。即static int x = 0;
只会在第一次调用count()函数时起效一次。