常见错误55:运行期静态初始化次序
所有C++代码中的静态数据都会被访问之前完成初始化。大多数情况下,此种初始化工作都会
完成与二进制镜像(program image)已加载,而代码的执行还未开始的时刻。如果未给
它们指定初始化物,它们就会被以全零模式(all zeros)初始化。
最好的预防运行期静态初始化困境的办法就是尽可能地减少外部链接的变量,包括静态的
class数据成员。
预防运行期静态初始化困境
把问题转化为对于在同一编译单元内初始化次序的相关性。
使用缓式评估求值来替代初始化。
我们可以显式地将初始化次序以代码形式固定下来。
尽量别用静态变量,永远都别做运行期静态初始化
term.h
#ifndef TERM_H
#define TERM_H
extern const char *terminalType;
//其他要初始化的东西
class InitMgr { // Schwarz 计数器
public:
InitMgr()
{ if( !count_++ ) init(); }
~InitMgr()
{ if( !--count_ ) cleanup(); }
void init();
void cleanup();
private:
static long count_; // 每个进程生成一个
};
namespace { InitMgr initMgr; } // 每次头文件包含生成一个
#endif
term.cpp
#include "term.h"
#include <cstdlib>
extern const char *terminalType = 0;
long InitMgr::count_ = 0;
void InitMgr::init() {
if( !(terminalType = std::getenv( "TERM" )) )
terminalType = "VT100";
// 其他的初始化工作
}
void InitMgr::cleanup() {
// 所有要求的清除工作
}
main.cpp
#include "term.h"
#include <iostream>
int main() {
using namespace std;
cout << "Terminal type is " << terminalType << endl;
return 0;
}