原文;
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Static_and_Global_Variables
規定程式中的non-local static object只能為POD,因為它們的ctor以及dtor的順序在C++中沒有被規範,這會造成難以解決的Bug;non-local static object為global或namespace scope的變數以及class中的static member data。
在同一個translation unit之中,global variables被初始化的順序即為它們被定義的順序。
class CFoo
{
public:
CFoo()
{
std::cout << "CFoo ctor" << std::endl;
}
};
class CBar
{
public:
CBar()
{
std::cout << "CBar ctor" << std::endl;
}
};
CFoo g_foo;
CBar g_bar;
void main()
{
std::cout << "Main" << std::endl;
}
在上面的sample code之中,我們可以保證g_foo一定會在g_bar之前被初始化。所以上面sample code輸出的順序必為:
CFoo ctor
CBar ctor
Main
但是C++的spec卻沒有規範不同的translation unit之間,global variables的初始化順序。比方說,在下方的sample code之中,我們將無法確定g_foo和g_bar哪一個會先被初始化,使用不同編譯環境可能會產生不同的結果:
========== MyHeader.h ==========
class CFoo
{
public:
CFoo()
{
std::cout << "CFoo ctor" << std::endl;
}
};
class CBar
{
public:
CBar()
{
std::cout << "CBar ctor" << std::endl;
}
};
========== AAA.cpp ==========
#include "MyHeader.h"
CFoo g_foo;
========== BBB.cpp ==========
#include "MyHeader.h"
CBar g_bar;
如果CBar的的初始化需要依賴g_foo的話,將會產生難以發現的bug:
class CBar
{
public:
CBar()
{
std::cout << "CBar ctor" << std::endl;
m_nNumber = g_foo.GetData();
}
private:
int m_nNumber;
};
因為我們無法確定處在不同translation unit的g_bar與g_foo哪一個會先被初始化。所以Google C++ Style Guide規定global variable只能為Plain Old Data (POD)。解決這個問題的方法有很多,但最好的辦法還是直接禁止non-POD的global variable。
Google C++ Style Guide也進一步禁止由global function的return value來初始化static POD,因為global function有可能會依賴某些global variables。
C++ spec指出dtor呼叫的順序為ctor呼叫順序的相反,因為non-local static objects的ctor呼叫的順序是未知的,所以它們的dtor呼叫的順序也是未知的。在某個non-local static object被銷毀的時候,很有可能其它的non-local static objects正在使用它(可能在其它的thread),因而造成bug。
如果真的要使用class type的global variable,Google C++ Style Guide建議,可以將之宣告為指標(不能為smart pointer),並且在main()或pthread_once()裡面為該指標作初始化,用以避免初始化順序不確定的問題。
關於這個問題,文獻上還有其它的解決方法。