標籤:

在c++中,靜態的對象的析構順序似乎是不可控的。?

有很多個靜態對象,哪個先析構呢?


同一個編譯單元內,是按照定義順序構造(逆序析構)。

不同編譯單元內的靜態對象,構造和析構順序都是不確定的。

以上是按照基本法。

關於上面答案里提到的static local object: local static object吼不吼? 當然吼。

然而 local static object的缺點:構造/析構順序雖然可控,但一般是在第一次調用的時候初始化。較為隱式化,不夠一目了然,依賴於執行路徑。當項目複雜到一定程度,這種可控程度或會降低,會出現同樣的析構順序問題

優點就是懶,不用費腦,比較隨意。也有方法在一定程度上檢測/預防上述問題。

項目里我有時候把有順序依賴的某部分對象定義一起放到一個cpp里,跟local static object搭配使用,特別是關於memeory/allocator的基本的foundation/utility library。到底哪個政治正確?還是看心情吧[滑稽],屬於coding style的問題,可以說是面對骨感的現實採取的不得已的奇技淫巧,沒什麼好糾結的。而關鍵,好的設計哲學,要盡量減少耦合和依賴。


謝邀,應該是和編譯器的鏈接順序有關,其實沒有必要在這個事上挑戰編譯器,最好的辦法就是避開這種自己控制不了的問題,不要在析構和構造函數中寫複雜的邏輯,而是寫在自己能控制的函數中。

我在程序中一般會盡量避免使用全局靜態變數,即使使用的話,也會通過一個全局靜態函數來獲得,就像下面這樣

static Foo getStaticFooObject(void) {
static Foo theStaticObject;
return theStaticObject;
}

這樣可以保證靜態對象在被調用的時候一定會被初始化過,析構函數可以用類似的方法。


From 《Effective C++》

... Static objects inside functions are known as local static objects, and the others are known as non-local static objects.

The relative order of initialization of non-local static objects defined in different translation unit(It is basically a single source file, plus all of its #include files) is undefined. There is a reason for this. Determining the "proper" order in which to initialize non-local static objects is hard. Very hard. Unsolvable hard. ...

... Add that has to be done is to move each non-local static object into its own function, where its declared static. The function return references to the objects they contains. In the other words, non-local static objects are replaced with local static objects.

This approach is founded on C++s guarantee that local static objects are initialized when the objects definition is first encountered during a call to that function.... As a bonus, if you never call a function emulating a non-local static object, you never incur the cost of constructing and destructing the object.

class FileSystem {...};
FileSystem fts() {
static FileSystem fs;
return fs;
}

書中把static object分為 全局靜態變數,定義在命名空間里的靜態變數,定義在函數里的靜態變數(local static object),定義在類裡面的靜態變數,和其他的靜態變數。

對於在不同文件里的非局部靜態變數,其初始化順序,是幾乎不可知的,可以認為是undefined

解決方案是,涉及到靜態變數,全部使用局部靜態變數。即通過函數返回局部靜態變數的引用即可確保使用時,該局部靜態變數已被初始化,這是C++標準保證的。


不是不可控的(隨機的),而是根據機器怎麼實現各自不同。

說實話,哪怕你知道順序是什麼,實際工作中,也不應該使用。

這種屬於你在自己卧室裡面放釘子——你自己知道醒來以後從左側下床前兩步右一步前一步左一步前兩步右兩步就可以毫髮無傷的走出去。

但哪天你喝醉了呢?你的曖昧對象來給你過生日呢?


當main函數結束之後,按照構造函數調用順序的相反順序進行析構。


推薦閱讀:

一道阿里實習生筆試題的疑惑?
學數據結構用C還是C++?
如何提升 C++ Trie 樹的存取效率?

TAG:C | 遊戲編程 |