2016-08-11 6 views
1

静的フィールド(#B)の初期化の前にグローバル変数の初期化(#A)を呼び出させます。特定の静的フィールドの前にグローバル変数を初期化するようにします

現在、一部の静的フィールドはグローバル変数の前に初期化されています。

GridUtil.h

class GridUtil{ 
    static Vec4* bPtr_; //will be filled 
    static void initGridCalculationCache(); 
    static class _init //helper class 
    { 
     public: 
     _init() { 
     static_iniAll(); 
     } 
    } _initializer; 

} 

GridUtil.cpp

#include "GridUtil.h" 
GridUtil::_init GridUtil::_initializer;// (Edit: This line is just added, thank Dietmar Kühl.) 
Vec4 b[24];      //#A executed 3rd : No, this should be the first. 
Vec4* GridUtil::bPtr_=b;   //#B executed 1st 
void GridUtil::initGridCalculationCache() { 
    //.... fill GridUtil::bPtr_ using complex computation //#C executed 2nd 
} 

結果

デバッグから、上記コードの実行順序は次のとおり -

B->C->A 

しかし、私がしたい: -

A->B->C 

私は "Vec4" を "INT" に置き換えられた場合、実行順序がなることに気づい: -

A->B->C 

目的自動的に呼び出される静的関数(initGridCalculationCache)を使用して配列の要素の値を設定します(クラス_initによって助けられます)。

できない場合は、それを行う正しい方法は何ですか?

+1

GridUtil.hを組み込む前にGridUtil.cppでグローバル変数を宣言しようとしましたか、それとも静的であると宣言しましたか? – wasthishelpful

+3

グローバル情報については、https://isocpp.org/wiki/faq/ctors#static-init-orderを参照してください。 – N0un

+0

@wasthishelpfulありがとう!それは正解ですが、あなたが望むなら答えとして投稿することができます。 – javaLover

答えて

3

4明白な解決策は以下のとおりです。

  1. ないで始まるするグローバルまたはstaticメンバ変数を持っています!これらは、並行性を利用するシステムでは、二重に大きな問題を生じる傾向があります。
  2. constexprオブジェクトは、コンパイル時に初期化されるため、使用してください。明らかに何ができるのかについていくつかの制約がありますが、コンパイラはオブジェクトが適切な順序で初期化されていることを検証します。
  3. 翻訳単位内では、静的ライブ時間のオブジェクトは上から下に初期化されます。つまり、変数定義が所望の順序を達成できる場合、適切な順序を使用します。しかし、翻訳単位全体にわたって可変な初期化を命ずるポータブルなアプローチはありません。
  4. 異なる翻訳単位のオブジェクト間の初期化に依存している場合、参照が返される関数ローカルstaticオブジェクトを使用して、正しい順序が保証されます。これらは、最初にアクセスされたときに構築されます。
+0

"3.翻訳単位内で、静的ライブ時間のオブジェクトは上から下に初期化されます。 OPのコードは、1つのTUで定義されたオブジェクトが上から下に初期化されていないようです。 – songyuanyao

+0

@songyuanyaoはい、OPのコードは初期化されていませんA-> B-> C。しかし、私が善意のアドバイス(#includeを動かす)をした後は、今は正しい。私はそれを明確にするために質問を編集しました。 DietmarKühlの記述は結果と一致しています。 – javaLover

+0

@javaLoverこれは、常に上から下に向かうのではなく、(関連するクラス定義などの位置のような)他のものに依存していますか?私はそれについて確かめたい。 – songyuanyao

0

順序はかなり単純ですが、PODはバイナリの.DATAセクションからRAMにコピーすることで初期化されます。クラスは、実行時にctorによって初期化されます。したがって、PODは、同じスタティックエリア内にある限り、すべてのクラスで初期化されます。 DLL/SOを使用すると、すべてが面白くなります。

初期化の順序は未定義です。何にも保証はありません。明示的に特別な注文が必要な場合は、静的変数をinit関数で初期化します。好みの順で

関連する問題