初始化問題

原文鏈接:http://harttle.com/2015/10/05/cpp-variable-init.html

定義基本數據類型變量(單個值、數組)的同時可以指定初始值,如果未指定C++回去執行默認初始化(default-initialization)。 那麼什麼是”默認初始化”呢?

  • 棧中的變量(函數體中的自動變量)和堆中的變量(動態內存)會保有不確定的值;
  • 全局變量和靜態變量(包括局部靜態變量)會初始化爲零。

C++11: If no initializer is specified for an object, the object is default-initialized; if no initialization is performed, an object with automatic or dynamic storage duration has indeterminate value. Note: Objects with static or thread storage duration are zero-initialized, see 3.6.2.

所以函數體中的變量定義是這樣的規則:

int i;                    // 不確定值
int i = int();            // 0
int *p = new int;         // 不確定值
int *p = new int();       // 0

靜態和全局變量的初始化

未初始化的和初始化爲零的靜態/全局變量編譯器是同樣對待的,把它們存儲在進程的BSS段(這是全零的一段內存空間)中。所以它們會被”默認初始化”爲零。

關於進程的內存空間分配見進程的地址空間:TEXT,DATA,BSS,HEAP,STACK一文。

來看例子:

int g_var;
int *g_pointer;
static int g_static;

int main(){
    int l_var;
    int *l_pointer;
    static int l_static;

    cout<<g_var<<endl<<g_pointer<<endl<<g_static<<endl;
    cout<<l_var<<endl<<l_pointer<<endl<<l_static<<endl;
};

輸出:

0                   // 全局變量
0x0                 // 全局指針  
0                   // 全局靜態變量
32767               // 局部變量
0x7fff510cfa68      // 局部指針
0                   // 局部靜態變量

動態內存中的變量在上述代碼中沒有給出,它們和局部變量(自動變量)具有相同的”默認初始化”行爲。

成員變量的初始化

成員變量分爲成員對象和內置類型成員,其中成員對象總是會被初始化的。而我們要做的就是在構造函數中初始化其中的內置類型成員。 還是先來看看內置類型的成員的”默認初始化”行爲:

class A{
public:
    int v;
};
A g_var;

int main(){
    A l_var;
    static A l_static;
    cout<<g_var.v<<' '<<l_var.v<<' '<<l_static.v<<endl;
    return 0;
}

輸出:

0 2407223 0

可見內置類型的成員變量的”默認初始化”行爲取決於所在對象的存儲類型,而存儲類型對應的默認初始化規則是不變的。 所以爲了避免不確定的初值,通常會在構造函數中初始化所有內置類型的成員。Effective C++: Item 4一文討論瞭如何正確地在構造函數中初始化數據成員。 這裏就不展開了,直接給出一個正確的初始化寫法:

class A{
public:
    int v;
    A(): v(0);
};

封閉類嵌套成員的初始化

再來探討一下當對象聚合發生時成員變量的”默認初始化”行爲,同樣還是隻關注於基本數據類型的成員。

class A{
public:
    int v;
};

class B{
public:
    int v;
    A a;
};

B g_var;
int main(){
    B l_var;
    cout<<g_var.v<<' '<<g_var.a.v<<endl;
    cout<<l_var.v<<' '<<l_var.a.v<<endl;
    return 0;
}

輸出:

0 0
43224321 -1610612736

規則還是是一樣的,默認初始化行爲取決於它所屬對象的存儲類型。 封閉類中成員對象的內置類型成員變量的”默認初始化”行爲取決於當前封閉類對象的存儲類型,而存儲類型對應的默認初始化規則仍然是不變的


發佈了34 篇原創文章 · 獲贊 11 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章