对象在使用之前的初始化

 C++规定对象的初始化动作发生在进入构造函数主体之前。(初始化列表比在构造函数体内初始化的效率高,以为在函数体内初始化会调用默认的构造函数)

编译单元是指产出单一目标文件的那些源码。

问题:

   两个源码文件,每个文件中至少有一个non-local static对象(即该对象是全局的或者位于namespace作用域内,或在class内或file的作用域内被声明为static)。如果某编译单元内的non-local static对象的初始化用动作使用了另一个单元内的某个non-local static对象,在这个时候由于c++对定义在不同的编译单元内的non-local static对象的初始化次序没有明确的规定,所以用可能引发错误。

例子:

你写的程序(一个编译单元):

class FileSystem
{
 public:
     …
     size-tnumDisk() const;
     …
};
Extern FileSystem tfs;//
准备给别人用的对象


别人的程序(另一个编译单元)

class Directory
{
  Directory(params)
{
   Size_tdisk=tfs.numDisks();   //使用第一个编译单元的对象,假设在编译这个文件之//前已经编译了上一个文件那么没错,如果相反呢?
}
};


解决办法:

   将每个non-local static对象搬到自己专属的函数内(也就是在函数内声明为static)。这些函数返回一个引用指向它所含的对象。在调用的时候调用这些函数而不是直接调用对象。理由(c++保证,函数内的local static对象会在该函数调用期间首次遇上该对象的定义式时被初始化)

程序修改之后:

class FileSystem
{
 public:
     …
     size-tnumDisk() const;
     …
};
FileSystem& tfs()
{  static FileSystem fs;
   returnfs;
}
 
 
Class Directory
{
  Directory(params)
{
       Size_tdisk=tfs().numDisks();   //调用函数tfs()
}
};
Directory& tempDir()
{
Static Directory td;
return td;
}

  任何一种non-conststatic对象不论他是local还是non-local,在多线程的环境下等待某事发生都会有麻烦,处理麻烦的做法是:在程序单线程启动的阶段手工调用引用返回的函数,这可以消除与初始化有关的竞速形式。

总结:

   一、对内置类型进行手工初始化(c++不保证初始化他们)。

   二、构造函数最好使用成员初始列,而不要在构造函数内使用赋值操作,初始列的次序应该和class中的声明次序相同。

   三、为免除跨编译单元的初始化问题,应该用local static对象替换non-local static对象。




你可能感兴趣的:(对象在使用之前的初始化)