C 中的全域初始化順序:忽略依賴關係
在C 中,翻譯單元內全域變數的初始化順序是明確定義的。但是,全域變數之間的依賴關係可以被忽略,從而導致令人驚訝的行為。
考慮以下程式碼:
<code class="cpp">struct Foo; extern Foo globalFoo; 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(); int main() { printf("main()\n"); return 0; }</code>
使用GCC 4.4.3 編譯時,預期輸出為:
Foo::Foo() Foo::addToGlobal() START Foo::add() Foo::addToGlobal() END main()
這是因為全域變數globalFoo是在呼叫靜態方法Foo::addToGlobal()之前初始化的。但是,如果我們交換 globalFoo 和虛擬聲明的順序,輸出將變為:
Foo::addToGlobal() START Foo::add() Foo::addToGlobal() END Foo::Foo() main()
看起來 Foo 的實例方法是在未建構的實例上呼叫的。這是因為全域初始化的順序忽略了依賴關係。
為了確保 Foo 的建構子在初始化 dummy 之前被調用,我們需要確保在同一翻譯單元中 globalFoo 在 dummy 之前定義。或者,我們可以使用指向全域實例的靜態指針,該指針在任何動態初始化之前將被初始化為 null。然後 addToGlobal 方法可以檢查指標是否為空,並在必要時建立全域 Foo。
以上是為什麼在 C 中交換全域變數宣告會導致意外行為?的詳細內容。更多資訊請關注PHP中文網其他相關文章!