在一个指定的翻译单元中,静态对象的初始化顺序严格按照对象在该单元中定义出现的顺序,而清除的顺序与初始化的顺序正好相反
Oof的构造函数依赖于out的存在,而此时out可能还没有创建,于是就可能引发问题
这个例子的情况很微妙,它能正常运行,分析如下:
但我们要注意的是,对于作用域为多个翻译单元的静态对象来说,不能保证严格的初始化顺序。这可能会引发一些问题,下面是一个能引起“灾难”的例子
//First file
#include <fstream>
std::ofstream out("out.txt");
//Second file
#include <fstream>
extern std::ofstream out;
class Oof
{
public:
Oof() { out << "Ouch"; }
} oof;
Oof的构造函数依赖于out的存在,而此时out可能还没有创建,于是就可能引发问题
现在来看看另外一个例子
//First file
#include <fstream>
extern int y;
int x = y + 1;
//Second file
#include <fstream>
extern int x;
int y = x + 1;
这个例子的情况很微妙,它能正常运行,分析如下:
对所有的静态对象,链接装载机制在程序员指定的动态初始化发生之前保证一个静态成员初始化为零,在第一个例子中,fstream out对象的存储空间赋零没有特别的意义,所以它在构造函数调用前是无定义的。然而对于内部数据类型,初始化为零是有意义的,在例子二重,如果First file先初始化,则y被赋为零,所以x为1,而后y被动态初始化为2,而如果初始化的顺序颠倒过来,则x被静态初始化为0,y被初始化为1,而后x被动态初始化为2
确保正确的初始化的方法,可以借鉴“函数内部的静态对象在函数第一次被调用时初始化,且只初始化一次”这个事实
一个示例代码:
//: Dependency1.h
#ifndef DEPENDENCY1_H
#define DEPENDENCY1_H
#include <iostream>
class Dependency1
{
bool init;
public:
Dependency1() : init(true)
{
std::cout << "Dependency1 construction"
<< std::endl;
}
void print() const
{
std::cout << "Dependency1 init: "
<< init << std::endl;
}
};
#endif // DEPENDENCY1_H ///:~
//:Dependency2.h
#ifndef DEPENDENCY2_H
#define DEPENDENCY2_H
#include "Dependency1.h"
class Dependency2
{
Dependency1 d1;
public:
Dependency2(const Dependency1& dep1): d1(dep1)
{
std::cout << "Dependency2 construction ";
print();
}
void print() const { d1.print(); }
};
#endif // DEPENDENCY2_H ///:~
//:Technique2.cpp
#include "Dependency2.h"
using namespace std;
// Returns a value so it can be called as
// a global initializer:
int separator()
{
cout << "---------------------" << endl;
return 1;
}
// Simulate the dependency problem:
extern Dependency1 dep1;
Dependency2 dep2(dep1);
Dependency1 dep1;
int x1 = separator();
// But if it happens in this order it works OK:
Dependency1 dep1b;
Dependency2 dep2b(dep1b);
int x2 = separator();
// Wrapping static objects in functions succeeds
Dependency1& d1()
{
static Dependency1 dep1;
return dep1;
}
Dependency2& d2()
{
static Dependency2 dep2(d1());
return dep2;
}
int main()
{
Dependency2& dep2 = d2();
} ///:~