2017-08-09 13 views
9

コードレビューでこのC++静的初期化順序関連のクエリが最近発生しました。クラスの静的メンバーの初期化は、そのクラスの静的オブジェクトの初期化前に保証されていますか?

  1. 私は私がしたい、ここで

異なるコンパイル単位でコンストラクタを使用して、そのクラスの静的オブジェクトをしました

  • コンパイル単位内の静的メンバ変数を持つクラスをしました静的オブジェクトコンストラクタが呼び出される前に静的メンバ変数が初期化されることが保証されているかどうかを確認しますか?

    MyClass.h

    typedef int (*MyFunc)(int); 
    class MyClass { 
    MyClass(MyFunc fptr) { 
        mFunc = fptr; 
    } 
    static MyFunc mFunc; 
    } 
    

    MyClass.cpp

    MyFunc MyClass::mFunc = nullptr; 
    

    MyDifferentClass.h

    MyDifferentClass { 
    public: 
        static int MyStaticFunc(int); 
    } 
    

    MyDifferentClass.cppmyClassObjが作成される前にコードで

    static MyClass myClassObj(MyDifferentClass::MyStaticFunc); 
    

    は、mFuncnullptrに初期化されるだろうか?クエリの理由は、注文が保証されていない場合、mFuncnullptrに再び初期化される可能性があるためです。コードで

  • +0

    不明な部分を許容する理由はなく、これをリンカーに任せることもできません。 main()の早い段階で明示的なコードを使ってシーケンスを保証するだけです。 –

    答えて

    6

    myClassObjが作成される前に、mFuncnullptrに初期化されるだろうか?クエリの理由は、注文が保証されていない場合、mFuncnullptrに再び初期化される可能性があるためです。

    質問に対する回答は「はい」です。

    スレッド固有のオブジェクトの初期化の問題を除いて、非ローカル変数の初期化は次の順序で実行されます。

    1. すべての変数はゼロで初期化されています(順序は指定されていません)。これはゼロ初期化と呼ばれます。
    2. 定数値を使用して初期化できるすべての変数が初期化されます。これは、定数の初期化と呼ばれます。

    これらは、スタティック初期化と呼ばれます。

    その後、動的初期化が実行されます。あなたのケースでは

    は、MyClass::mFunc動的初期を使用して初期化されmyClassObjながら定数の初期化を使用して初期化されます。したがって、前者は最初に初期化されることが保証されています。

    このトピックの詳細はhttps://timsong-cpp.github.io/cppwp/n3337/basic.start.initにあります。

    +1

    あなたはC++ 11を引用していますが、様々な理由で[basis.startが欠陥レポート2026のために変更されました](https://stackoverflow.com/a/34276374/1708801)。ので注意してください。 –

    +0

    @ShafikYaghmour、ありがとう。それは良い情報です。 –

    関連する問題