面试题答案
一键面试执行顺序确定
- 同一编译单元内:在同一个编译单元中,类的静态对象的构造函数按照它们在源文件中声明的顺序执行。例如,如果在源文件中先声明
static ClassA a;
后声明static ClassB b;
,那么ClassA
的构造函数会在ClassB
的构造函数之前执行。 - 不同编译单元间:在不同编译单元中,类的静态对象的构造函数执行顺序是未定义的。这意味着在不同编译单元中的静态对象构造函数执行顺序可能会因编译器、链接器和运行环境的不同而有所差异。例如,在一个编译单元中定义了
static ClassC c;
,在另一个编译单元中定义了static ClassD d;
,无法确切知道c
和d
的构造函数谁先执行。
确保特定执行顺序的方法
- 单例模式:可以将需要特定顺序初始化的静态对象改为单例模式。在单例模式中,对象在第一次被使用时进行初始化,这样可以通过控制使用的顺序来间接控制初始化顺序。例如:
class Singleton {
public:
static Singleton& getInstance() {
static Singleton instance;
return instance;
}
private:
Singleton() {}
~Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
};
然后在其他地方使用Singleton::getInstance()
来获取单例对象,通过控制调用getInstance
的顺序来确保初始化顺序。
2. 全局函数:将初始化代码放到全局函数中,并在main
函数中按照特定顺序调用这些全局函数。例如:
class ClassE {};
class ClassF {};
void initE() {
static ClassE e;
}
void initF() {
static ClassF f;
}
int main() {
initE();
initF();
// 其他代码
return 0;
}
这样ClassE
的初始化会在ClassF
之前。
3. 依赖注入:可以通过依赖注入的方式,将依赖的对象作为参数传递给需要初始化的对象,从而确保依赖对象先初始化。例如:
class Dependency {
public:
Dependency() {}
};
class Dependent {
public:
Dependent(Dependency& dep) : dep(dep) {}
private:
Dependency& dep;
};
int main() {
Dependency dep;
Dependent deped(dep);
// 其他代码
return 0;
}
这里Dependency
对象先初始化,然后Dependent
对象依赖于Dependency
对象进行初始化。