请记住:
- 为内置对象进行手工初始化,C++不保证初始化。
- 构造函数最好使用 成员初值列 ,而不要在构造函数内使用赋值操作。且成员变量的排列次序与Class中声明的相同
- 为免除“跨编译单元之初始化次序”问题,请用local static对象替换non-local static对象
准则理解:
用成员初值列替代初始化而不是赋值。
简单的理解,类数据成员可以是string、vector、list或者其他的类。若使用赋值语句,在进入构造函数函数体进行赋值首先调用这些类的默认构造函数,再使用这些类的复制构造函数进行赋值。而不进入函数体赋值,使用成员初值列进行初始化,实际上是只使用的这些类的构造函数(非默认)。后者效率明显要高一些。为免除“跨编译单元之初始化次序”问题,请用local static对象替换non-local static对象。
具体例子:
文件1:
class FileSys
{
public:
size_t numDisks() const;
};
extern FileSys tfs;
文件2:
class Diectory
{
public:
Directory(param);
};
Directory::Directory(param)
{
size_t disks=tfs.numDisck();
}
Directory tempDir(params);
当文件2用户创建一个Directory 对象temDir时,可能会出现一个问题:temDir的构造函数可能会用到尚未初始化的tfs,除非能保证tfs在tempDir之前初始化。但是tempDir和tfs是不同时间不同人不同源码文件建立起来的,所以肯定不能保证。
考虑将每个non-local static对象搬到自己的专属函数内(声明为static),这些函数返回一个应用指向它所含的对象,然后其他的地方调用这些函数,而不直接指涉这些对象。
文件1:
class FileSys
{
public:
size_t numDisks() const;
static FileSys & tfs();
};
FileSys& FileSys::tfs()
{
static FileSys fs; // 定义并初始化一个local static 对象
return fs;
}
文件2:
class Diectory
{
public:
Directory(param);
};
Directory::Directory(param)
{
size_t disks=FileSys::tfs().numDisck();
}
Directory& tempDir()
{
static Directory td; //定义并初始化local static对象
return td;
}
这样在文件2中调用tempDir返回我们需要的Directory对象可以保证tfs一定已经初始化,注意默认构造函数中是tfs().numDisck()而不是tfs.numDisck()。
一个更简单的例子:
文件1:
int a = 1;
文件2:
extern int a;
int b = a * 3;
同样的存在问题:文件1和文件2谁在前?只有文件1在前才能保证b的输出正确。
同样的改进:
文件1:
int &GetA()
static int a =1;
return a;
文件2:
int b = GetA() * 3;
则可以解决问题。所以跨编译单元的初始化问题,用local static对象替换non-local static对象。方法的重要思想是不要使变量有全局的作用域。
参考:https://www.cnblogs.com/jerry19880126/archive/2013/03/09/2951186.html