面试题答案
一键面试globalVar
- 初始化顺序:在程序启动时,在main函数执行之前进行初始化。对于跨编译单元(不同源文件)的全局变量,其初始化顺序是未定义的。如果一个全局变量的初始化依赖于另一个全局变量,可能导致未定义行为。例如,如果源文件A中的
globalVarA
初始化时依赖源文件B中的globalVarB
,而globalVarB
可能在globalVarA
之后初始化,这就会出现问题。 - 作用域:全局作用域,从定义处开始到整个程序结束都可见。在不同源文件中,如果要使用该全局变量,需要使用
extern
关键字声明。例如,在源文件A中定义int globalVar = 10;
,在源文件B中可以extern int globalVar;
,然后就可以使用globalVar
。 - 初始化相关问题及避免方法:
- 问题:跨编译单元全局变量初始化顺序不确定问题。
- 避免方法:可以通过设计模式来解决,比如使用单例模式。将全局变量封装在一个类中,通过静态成员函数来获取该变量的实例,这样可以控制初始化顺序。例如:
class GlobalVarHolder {
public:
static int& getGlobalVar() {
static int globalVar = 10;
return globalVar;
}
};
在其他源文件中使用GlobalVarHolder::getGlobalVar()
来访问该全局变量,确保了在第一次使用时初始化。
localVar
- 初始化顺序:每次进入声明它的代码块时进行初始化。例如:
void func() {
int localVar;
{
int localVar = 5; // 这里的localVar是新的局部变量,仅在这个代码块内有效
// 初始化顺序:进入这个代码块时,初始化这个localVar为5
}
// 这里的localVar是函数开头声明的localVar,还未初始化
}
- 作用域:局部作用域,仅限于声明它的代码块内。当离开该代码块时,变量的生命周期结束,其占用的内存被释放。
- 初始化相关问题及避免方法:
- 问题:在函数内部不同代码块多次声明同名局部变量,可能会导致混淆,并且如果在使用前未初始化,会导致未定义行为。例如:
void func() {
int localVar;
// 使用localVar未初始化会导致未定义行为
{
int localVar = 5;
// 这里的localVar和上面的不是同一个
}
// 这里再次使用函数开头声明的localVar,如果未初始化会有问题
}
- 避免方法:尽量避免在函数内部不同代码块多次声明同名局部变量。如果确实需要在不同代码块使用类似功能的变量,可以使用不同的命名。同时,确保在使用变量之前进行初始化。例如:
void func() {
int localVar = 0; // 初始化localVar
{
int anotherVar = 5; // 使用不同的命名
}
// 此时localVar已初始化,可以安全使用
}