定義沒有初始化式的變量時,系統有時候會幫我們初始化變量。系統如何初始化取決於變量的類型以及變量定義的位置。
內置類型變量是否自動初始化取決於變量定義的位置。函數體外定義的變量初始成0;函數體內定義的變量不進行自動初始化。除了用作賦值操作的左操作數,其他任何使用未初始化變量的行為都是未定義的,不要依賴未定義行為。
以int類型為例,一段簡單的測試代碼:
#include <iostream> using namespace std; int a; int main() { int b; cout << a << endl; cout << b << endl; return 0; }
在VS執行這段代碼,輸出變量a的值0,同時VS會報錯:Run-Time Check Failure #3 — The variable 'b' is being used without being initialized。 變量a被自動初始化為0;變量b未被自動初始化。
類類型變量在定義時,如果沒有提供初始化式,則會自動調用默認構造函數進行初始化(不論變量在哪里定義)。如果某類型沒有默認構造函數,則定義該類型對象時必須提供顯示初始化式。
一段簡單的測試代碼(默認構造函數由編譯器自動生成):
#include <iostream> using namespace std; class testA { public: void printf() const { cout << data << endl; } private: int data; }; testA a; int main() { testA b; a.printf(); b.printf(); return 0; }
在VS執行這段代碼,得到以下結果:

編譯器自動生成的默認構造函數使用與變量初始化相同的規則來初始化數據成員。對象a在函數體外定義,其int類型數據成員被初始為0;對象b在函數體內定義,合成默認構造函數不會對其進行初始化(符合內置類型變量初始化規則),其中存放的都是隨機值。同樣,如果數據成員是類類型,則會調用相應的默認構造函數對數據成員進行初始化。
如果稍微改變一下這個類的定義,定義一個構造函數以阻止編譯器自動生成默認構造函數:
#include <iostream> using namespace std; class testA { public: testA(int a) { data = a; } void printf() const { cout << data << endl; } private: int data; }; testA a; int main() { testA b; a.printf(); b.printf(); return 0; }
這段代碼無法通過編譯:error C2512: “testA”: 沒有合適的默認構造函數可用。
定義數組時,如果沒有顯示提供初始化列表,則數組元素的自動化初始規則同普通變量一樣:函數體外定義的內置類型數組,其元素初始為0;函數體內定義的內置類型數組,其元素無初始化;類類型數組無論在哪里定義,皆調用默認構造函數進行初始化,無默認構造函數則必須提供顯示初始化列表。
如果定義數組時,僅提供了部分元素的初始列表,其剩下的數組元素,若是類類型則調用默認構造函數進行初始,若是內置類型則初始為0(不論數組定義位置)。
對於動態分配的數組,如果數組元素是內置類型,其元素無初始化;如果數組元素是類類型,依然調用默認構造函數進行初始化。也可以在使用跟在數組長度后面的一對空圓括號對數組元素做值初始化。
例如: int *ptrA = new int[10];
int *ptrB = new int[10] ();
其中ptrA指向的動態數組其元素未初始化,而ptrB指向的動態數組元素被初始化為0。
對於動態分配的單個對象,可使用直接初始化的語法規則在定義時顯示初始化。如果不提供顯示初始化式,動態創建的對象與在函數內部定義的變量初始化方式相同(即:內置類型無初始化,類類型調用默認構造函數進行初始化)。
