确定对象被使用前已经初始化
不同编译单元内定之non-local static
对象的初始化次序是不确定的
广义的static
对象包括:
global
对象- 定义于
namespace
作用域内的对象 - 在
class
内、函数内、file
作用域内声明为static
的对象
local static
:定义在函数内的static
对象
比如我有两个类FileSystem
和Directory
FileSystem
的声明和定义
class FileSystem {
public:
FileSystem(int a) : num(a) {}
std::size_t getNum() const;
private:
int num;
};
#include "FileSystem.h"
std::size_t FileSystem::getNum() const {
return num;
}
Directory
的声明和定义
#include "FileSystem.h"
class Directory {
public:
Directory();
int display();
private:
int val;
};
#include "Directory.h"
extern FileSystem tfs; // 这里声明了一个FileSystem对象,因为Directory的初始化要用到
Directory::Directory() {
std::size_t disks = tfs.getNum();
val = disks;
}
int Directory::display() {
return val;
}
Directory tempDir; // 定义一个Directory对象
tfs
的定义
#include "FileSystem.h"
FileSystem tfs(10);
main
函数
#include "Directory.h"
#include <iostream>
using namespace std;
extern Directory tempDir;
int main(int argc, char const *argv[])
{
cout << tempDir.display() << endl;
return 0;
}
0
发现输出不是我们预期的10
,原因在于定义dir
时调用了Directory
的构造函数,用到了FileSystem
的对象tfs
,但这个tfs
此时未必已经初始化了,因为编译器对文件的编译顺序没有严格的要求,所以会出现问题
解决办法
不要把tfs
声明为全局变量,即non-local static
变量,而要声明为local static
,就是函数里面的static
变量
#include "Directory.h"
extern FileSystem& tfs();
Directory::Directory() {
std::size_t disks = tfs().getNum();
val = disks;
}
int Directory::display() {
return val;
}
// Directory dir; // dir也声明为non-local static
Directory& dir() {
static Directory tempDir;
return tempDir;
}
#include "FileSystem.h"
// FileSystem tfs(10);
FileSystem& tfs() {
static FileSystem fs(10); // 在函数里面定义,就是local static
return fs; // 返回引用
}
#include "Directory.h"
#include <iostream>
using namespace std;
extern Directory& dir();
int main(int argc, char const *argv[])
{
cout << dir().display() << endl;
return 0;
}
10
这样就符合我们的预期了tfs()
函数内部实现了FileSystem
对象的初始化,调用该函数之后,就可以确保对象一定会被初始化了
所以用调用函数替换直接使用non-local static
对象,就可以得到对象初始化保证