閱讀382 返回首頁    go 外匯


C++編程規範之21:避免跨編譯單元的初始化依賴

摘要:

    保持順序,不同編譯單元中的名字空間級對象決不應該在初始化上互相依賴,因為其初始化順序是未定義的。這樣做會惹出很多麻煩,輕則在項目中稍做修改就會引發奇怪的崩潰,重則出現嚴重的不可移植問題——即使是同一編譯器的新版本也不行。

    在不同的編譯單元中定義兩個名字空間級的對象時,先調用哪一個對象的構造函數是沒有定義的。經常工具可能會碰巧按照編譯單元目標文件的連接順序初始化,但這種假設並不總是可靠的;即使確實如此,你總不會希望自己的代碼的正確性難以捉摸地依賴於makefile或者項目文件吧。

    因此,在任何名字空間級對象的初始化代碼中,不能假設其他編譯單元中定義的任何其他對象都已經初始化了。這些考慮方法也適用於動態初始化的原始類型變量。

    請注意,甚至在使用構造函數構造之前,名字空間級對象就已經使用0靜態初始化過了。有些自相矛盾的是,這種零初始化會使錯誤更難以檢查,因為靜態的零初始化不會迅速使程序崩潰,而是使未初始化對象顯現出一種看似合理的表象。你可能認為字符串是空的,指針是空的,整數型變量為0,而事實上,代碼已經費勁地將它們初始化了。

    為了避免這一問題,應該盡可能地避免使用名字空間級的變量,它們很危險。如果確實需要可能依賴於另一個變量的此種變量,可以考慮使用singleton設計模式。使用時要小心一些,可以通過確保對象在第一次訪問時被初始化,來避免隱含的依賴性。Singleton本質上也是全局變量,它會因為相互依賴或者循環依賴而被破壞。

最後更新:2017-04-03 12:53:43

  上一篇:go J2EE的web.xml中filter-mapping的位置導致的亂碼問題
  下一篇:go 連載:麵向對象葵花寶典:思想、技巧與實踐(2) - 麵向對象語言發展曆史