C グローバル初期化順序: 依存関係の探索
C では、通常、翻訳単位内のグローバル変数は宣言された順序で初期化されます。ただし、複数の翻訳単位にわたる初期化順序を考慮すると、混乱が生じる可能性があります。
初期問題のシナリオ
次のコードを考えてみましょう。
<code class="cpp">struct Foo { Foo() { printf("Foo::Foo()\n"); } void add() { printf("Foo::add()\n"); } static int addToGlobal() { globalFoo.add(); return 0; } }; Foo globalFoo; int dummy = Foo::addToGlobal(); int main() { printf("main()\n"); return 0; }</code>
Withこのコードでは、期待される出力は次のとおりです:
Foo::Foo() Foo::addToGlobal() START Foo::add() Foo::addToGlobal() END main()
ただし、dummy と globalFoo の宣言と初期化を交換すると、別の出力になります:
Foo::addToGlobal() START Foo::add() Foo::addToGlobal() END Foo::Foo() main()
初期化の順序と依存関係
この動作は、グローバル変数の初期化順序が依存関係を無視していることを示唆しています。この場合、Foo::addToGlobal() への呼び出しは、コンストラクターが呼び出される前に Foo のメソッドにアクセスしようとします。
解決策: 正しい初期化を確保する
ダミーが初期化される前に Foo のコンストラクターが確実に呼び出されるようにするには、同じ翻訳単位でダミーの前に globalFoo を定義します。これにより、globalFoo が最初に初期化されることが保証され、addToGlobal() がそのメソッドに正常にアクセスできるようになります。
代替解決策: 静的初期化ガード
あるいは、静的メソッドを導入することもできます。 Foo::addToGlobal():
<code class="cpp">static Foo* pFoo = nullptr; if (pFoo == nullptr) { pFoo = &globalFoo; } pFoo->add();</code>
内の初期化ガード。このチェックにより、メソッドにアクセスする前にポインタ pFoo が globalFoo に初期化されていることを確認し、globalFoo の時期尚早な使用を効果的に防止します。
以上が依存関係のある C でグローバル変数の適切な初期化を保証する方法は?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。