close

原文;
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()裡面為該指標作初始化,用以避免初始化順序不確定的問題。

關於這個問題,文獻上還有其它的解決方法。

arrow
arrow
    文章標籤
    C++
    全站熱搜

    coherence 發表在 痞客邦 留言(0) 人氣()