2017-08-09 80 views
9

我最近在代碼審查中遇到了這個與C++靜態初始化相關的查詢。初始化該類的靜態對象的初始化之前是否保證了類的靜態成員的初始化?

  1. 我和靜態成員變量類編譯單元
  2. 我在不同的編譯單元

這裏使用一個構造函數,類的靜態對象,我想知道靜態成員變量是否保證在靜態對象構造函數被調用之前被初始化?

MyClass.h

typedef int (*MyFunc)(int); 
class MyClass { 
MyClass(MyFunc fptr) { 
    mFunc = fptr; 
} 
static MyFunc mFunc; 
} 

MyClass.cpp

MyFunc MyClass::mFunc = nullptr; 

MyDifferentClass.h

MyDifferentClass { 
public: 
    static int MyStaticFunc(int); 
} 

MyDifferentClass.cpp

static MyClass myClassObj(MyDifferentClass::MyStaticFunc); 

在代碼中,將mFunc被初始化爲nullptrmyClassObj之前被創造出來的?查詢的原因是,如果訂單不能保證,那麼mFunc可能會重新初始化爲nullptr

+0

沒有理由容忍未知,也不會將其留給鏈接器。只需在main()的早期使用顯式代碼來確保序列。 –

回答

6

在代碼中,將mFunc被初始化爲nullptrmyClassObj之前被創造出來的?查詢的原因是,如果訂單不能保證,那麼mFunc可能會重新初始化爲nullptr

該問題的答案是「是」。

拋開線程指定對象的初始化問題,非局部變量的初始化按以下順序執行。

  1. 所有變量都是零初始化的(未指定順序)。這被稱爲零初始化
  2. 所有可以使用常量值初始化的變量都被初始化。這稱爲不斷初始化

那些(上述1和2)被稱爲靜態初始化

之後,執行動態初始化。

在你的情況,MyClass::mFunc使用常數初始化myClassObj使用動態初始化初始化初始化。因此,前者保證首先被初始化。

有關此主題的更多信息,請訪問https://timsong-cpp.github.io/cppwp/n3337/basic.start.init

+1

由於各種原因,您正在引用C++ 11,但引用了很多[basis.start因缺陷報告2026](https://stackoverflow.com/a/34276374/1708801)而更改。所以要小心。 –

+0

@ShafikYaghmour,謝謝。這是很好的信息。 –