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>
與這段程式碼,預期的輸出是:
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 的構造函數在dummy 初始化之前被調用,我們可以在同一翻譯單元中在dummy 之前定義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中文網其他相關文章!