C 中的全域初始化順序與相依解析
在C 中,單一翻譯單元內的全域變數依照定義的順序進行初始化。然而,不同翻譯單元之間的全域變數沒有明確定義的順序。這種歧義可能會導致意外的行為,如以下程式碼所示:
<code class="cpp">struct Foo { Foo() { printf("Foo::Foo()\n"); } void add() { printf("Foo::add()\n"); } static int addToGlobal() { printf("Foo::addToGlobal() START\n"); globalFoo.add(); printf("Foo::addToGlobal() END\n"); return 0; } }; Foo globalFoo; int dummy = Foo::addToGlobal();</code>
當在初始化globalFoo 之前調用addToGlobal 時,行為符合預期:
Foo::Foo() Foo::addToGlobal() START Foo::add() Foo::addToGlobal() END main()
但是,當當順序顛倒時,不會呼叫Foo 的建構函數,並且可以在addToGlobal 中以某種方式存取 globalFoo:
Foo::addToGlobal() START Foo::add() Foo::addToGlobal() END Foo::Foo() main()
此行為歸因於以下事實:全域變數的初始化順序忽略了它們之間的任何依賴關係。在這種情況下,dummy 依賴 globalFoo,但不能保證它們的初始化順序。
為了確保在使用 globalFoo 之前呼叫 Foo 的建構函數,一種解決方案是建立一個指向全域實例的靜態指標並進行測試addToGlobal 中是否為 null。如果為 null,則在任何動態初始化之前建立全域 Foo。
以上是為什麼不同翻譯單元中的全域變數會導致 C 中的意外行為?的詳細內容。更多資訊請關注PHP中文網其他相關文章!