0

こんにちは、この質問で、コンパイルの順序は重要ではないことを読みましたが、本当に奇妙な状況にあります。

ファイル CCSizePolicy.cpp にはいくつかのグローバル変数があります。それらは次のようになります。

const CCSizePolicy CCSizePolicyWrapContent ( Const::WRAP_CONTENT );
const CCSizePolicy CCSizePolicyMatchContent ( Const::MATCH_PARENT );
const CCSizePolicy CCSizePolicyZero ( Policy::SP, 0 );

ヘッダーに

    enum Const
    {
        WRAP_CONTENT = -1, MATCH_PARENT = -2
    };

extern const CCSizePolicy CCSizePolicyWrapContent;
extern const CCSizePolicy CCSizePolicyMatchContent;
extern const CCSizePolicy CCSizePolicyZero;

CCLayoutParams.h にもあります

extern const CCLayoutParams CCLayoutParamsMatchMatch;
extern const CCLayoutParams CCLayoutParamsWrapWrap;
extern const CCLayoutParams CCLayoutParamsMatchWrap;
extern const CCLayoutParams CCLayoutParamsWrapMatch;

および CCLayoutParams.cpp

const CCLayoutParams CCLayoutParamsMatchMatch ( CCSizePolicyMatchContent,
        CCSizePolicyMatchContent );

const CCLayoutParams CCLayoutParamsWrapWrap ( CCSizePolicyWrapContent,
        CCSizePolicyWrapContent );

const CCLayoutParams CCLayoutParamsMatchWrap ( CCSizePolicyMatchContent,
        CCSizePolicyWrapContent );

const CCLayoutParams CCLayoutParamsWrapMatch ( CCSizePolicyWrapContent,
        CCSizePolicyMatchContent );

したがって、プログラムでそれらを使用するときは、 CCLayoutParamsWrapWrap.getWidth() および CCLayoutParamsWrapWrap.getHeight() を呼び出します

これは私に -1 -1 を出力するはずですが、私は 0 0 を持っています...

makefile での順序は次のようになります。

src/view/layout/CCLayoutParams.cpp\
...
src/view/CCSizePolicy.cpp\

に変更すると

src/view/CCSizePolicy.cpp\
src/view/layout/CCLayoutParams.cpp\
...

すべてが機能し始めます (私は -1 -1 を取得します) 何が起こっているのですか?

gcc バージョン 4.6.3 で Linux を使用しています (Ubuntu/Linaro 4.6.3-1ubuntu5)

ソース ファイルを名前で並べ替えているため、プロジェクト全体にバグが発生しています。なぜでしょうか??!?!

4

2 に答える 2

2

ほとんどの場合、ファイルがコンパイルされた順序ではありませんが、実際にはリンクされている順序です(ソースがある順序で定義されていると思います)-g ++は、リンク段階で変数のグローバルな初期化を「収集」しますとなり、見つかった順に処理されます。ただし、これはたまたま「観察された動作」です。C++ の異なるコンパイル ユニット間の初期化は未定義です。何らかの形であることに依存してはいけません.g ++がグローバル初期化を配置する順序を変更して、現在の順序ではなく逆の順序で実行されることを妨げるものはまったくありません(リンクプロセスが高速になるため) 、またはその他の巧妙な理由、または単に「そう感じた」)-そして、彼らはそうしたことをあなたに伝える必要さえありません。

したがって、基本的に、グローバル オブジェクトがある場合は、それらを単一のソース ファイル ("globalobjects.cpp" など) に入れて定義された順序で初期化するか、以前に初期化されたものに依存しないようにする必要があります。別。または、「現在、ファイルを正しい順序で配置している限り、リンカーは正しい順序で処理を実行する」という漠然とした定義に依存します。

于 2013-07-20T20:40:27.233 に答える
2

異なるソース ファイルでのグローバルの初期化の順序は規定されていません。そのため、ファイルがコンパイルされる順序など、あらゆるものに依存する可能性があります。

この場合、CCLayoutParamsWrapWrapが の前に初期化されると、そのコンストラクタはのコンストラクタによって設定されたCCSizePolicyWrapContent値を認識しません。代わりに、いわゆる「静的初期化」によって設定された値が表示されます。これは、「動的初期化」(つまり、コンストラクター呼び出し) の前に行われます。-1CCSizePolicyWrapContent0

gcc の何が違いを引き起こしているのか、具体的にはわかりませんが、本当に重要なのはコンパイル順ではなく、リンク順だと思います。ただし、これは推測にすぎません。確認または反論したい場合は、テストできます。重要な点は、そのように振る舞う必要がないので、それに頼るべきではないということです。

C++11 では、コンストラクターをCCSizePolicyWrapContent持つconstexprオブジェクトであることを確認することで、これを修正できると思います。constexprそれ以外の場合は、「静的初期化順序の大失敗」と、初期化順序に制約を課すために使用できるさまざまな手法について読んでから、状況に合ったものを選択する必要があります。

于 2013-07-20T20:34:13.617 に答える