定义没有初始化式的变量时,系统有时候会帮我们初始化变量。系统如何初始化取决于变量的类型以及变量定义的位置。
内置类型变量是否自动初始化取决于变量定义的位置。函数体外定义的变量初始成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。
对于动态分配的单个对象,可使用直接初始化的语法规则在定义时显示初始化。如果不提供显示初始化式,动态创建的对象与在函数内部定义的变量初始化方式相同(即:内置类型无初始化,类类型调用默认构造函数进行初始化)。