类成员初始化和赋值的内幕
扫描二维码
随时随地手机看文章
定义一个变量,就是在内存中为你定义的这个变量开辟一段内存空间,如果这个变量没有初始化,那么系统会随机给这个变量赋一个值,这个值我一般称它为"垃圾数"。没有初始化的变量我认为它是没有意义的,是在浪费内存,就比如人刚出生的时候上帝需要给他赋予点东西,比如条件反射,比如哭,比如吮吸........这样人的意义得以体现。对于类的成员来说,我们最好的做法就是在构造函数中对每一个类成员进行初始化。
我们来看一个简单的例子:
class name{public: name(int aa, int bb) {}private: int a; int b;};
上面例子中的变量 a 和 b 的值都没有在构造函数中初始化,这时候它们的值就会是一个"垃圾数",我们稍微改一下:
class name{public: name(int aa, int bb):a(aa) { b = bb; }private: int a; int b;};
可以看到 a 的值是用初始化列表的方式进行初始化,而 b 的值是通过构造函数的参数进行赋值。
在类对象调用构造函数的时候,以上两种方式都可以确保 a 和 b 的值是可以确定的,但是初始化和赋值两种方式是有区别的:
初始化发生的时机肯定比赋值早。初始化会在程序刚开始运行的时候发生,而赋值是只有在程序执行到这条语句才会发生。
初始化的执行效率要比赋值高。类成员在构造函数中执行的赋值语句之前已经被系统进行了初始化,当执行赋值的时候就需要抹掉之前default的初始化的数据,这样就相当于多做了一次无用功,而构造函数中运行的初始化列表则不需要做这次无用功。
常量成员和引用成员只能使用初始化列表。这是c++的语法。
class name{public: name(int aa, int bb):b(bb),a(aa) {}private: int const a; int &b;};
代码中的类成员 a 和 b 是必须使用初始化列表初始化的,这是c++语法规定的。
另外,类成员的初始化的顺序的固定的:如果有基类的话,先初始化基类,然后按照类中声明的顺序去初始化派生类中的类成员。上述代码中可以看到,构造函数初始化列表是先写 b 后写 a,即使是这样也是会按声明的顺序先初始化 a 后初始化 b。
我们来做一个实验就可以彻底明白:
class Name{public: Name():b(2),a(b + 2) {} void print() { cout << "a = " << a << " , b = " << b << endl; }private: int const a; int b;}; int main(){ Name Leon; Leon.print(); return 0;}
编译后的结果为:
结果很明显,当初始化 a 的时候,b还没被初始化为2,b还是个垃圾数,所以最终打印的 a 的值依然是个垃圾数,b 则后面被初始化为 2。