玩命加载中 . . .

04-初始化


确定对象被使用前已经初始化

不同编译单元内定之non-local static对象的初始化次序是不确定的

广义的static对象包括:

  • global对象
  • 定义于namespace作用域内的对象
  • class内、函数内、file作用域内声明为static的对象

local static:定义在函数内的static对象

比如我有两个类FileSystemDirectory

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对象,就可以得到对象初始化保证


文章作者: kunpeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kunpeng !
  目录