對象在使用之前的初始化

 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對象。




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章