首先这里都是一家之言自我高潮,很可能出现错误,如果有幸大佬肯看并且发现错误请予以指正避免误人子弟。我写的这些东西纯属自嗨,请勿轻信。
初始化列表,是C++构造函数专属的一个语法,用于初始化成员变量。
那么用它初始化 与 在构造函数体里边直接给成员赋值有什么区别?
我认为,想理解这一点,关键是理解初始化和赋值不是一回事
只要理清了什么是初始化,一切都好说
什么叫初始化?
我常听说:初始化就是给变量赋初值。纯属屁话。什么叫初值?为什么非要赋个初值?
我的理解是,你创建一个变量,它开辟了一块内存空间。开辟空间后,这空间里边必须有点东西,你不能什么也不放,这空间不能是”真空“。这时候往里边放某个值,就叫初始化。你可以利用一些语法自己主动的初始化,如果你不手动初始化,此时要么变量自己自动的初始化,要么就报错。
比如你 int a; 没有手动的去初始化它,但是他指代的内存空间里也不是空的,而是自动的被初始化了。在C++中,局部变量自动初始化的就是随机的int值。你int *p;你没手动初始化直接用了,这个指针变量里边也是个随机的地址值。野指针就这么来的。
或者说,变量需要有个值才能被成功的创建,此时为了能成功创建变量而做出的‘赋值“行为就叫初始化。
我们看看定义一个普普通通的变量时,常用的手动初始化的语法是什么?就是
int a=10;
这看起来就像只是在声明时顺便给变量赋个值。所以大伙把初始化和赋值整混了。其实这种初始化方法叫做拷贝初始化,是把等号右侧的东西复制给新创建的变量让他初始化。
其实最正经的初始化方法应该是这样的
int a(10);
用小括号这种就叫直接初始化。
初始化其实有好几种写法。这里就不多说了,因为很浅。
现在看看初始化列表
人都说,构造函数的执行过程分为两步:先是初始化阶段,后计算阶段。
计算阶段就是执行函数体内容。
初始化阶段干的是什么?我们想着,先把成员变量先给创建好,准备好,然后再考虑往下执行构造函数体里的代码。这看起来很合乎逻辑,我函数体可不就是要用成员变量,没发面和馅你包什么饺子啊。可是你要创建变量,你得初始化啊。初始化阶段就干这个的。
那么大伙研究的挺好,在执行这个函数体之前,你得先把我这个成员变量给创建,初始化喽。初始化你得给他一个值啊?因此就又分成两种情况。如果你写了初始化列表,写谁谁谁,你是什么什么值,大伙一瞧得咧,就照你说的来,我就初始化这个值。这是好的情况,谁也没问题。
那,你要是没写初始化列表呐?平时的成员变量倒好说,人家会自动初始化。本来吗,你声明一个变量不给他初始化他就随便找个随机的值装上。然后你在构造函数体里,乐意赋个值,就把他们改了。
可其中一个问题是,你让那const 常量,和那引用怎么办?这俩爷,必须要在定义时手动初始化,而且初始化完了就不许改。你没写初始化列表他们俩人没辙啊。怎么办?简单!直接完蛋。报错。
所以说,因为const常量和引用的初始化必须人为控制,所以要写在初始化列表里。这是用初始化列表的其中一个原因。
有人说那不对啊,你平时,怎么定义引用,怎么定义常量啊?不就int &a = b;你直接这么写不就得了?非那么大劲干嘛?
谁吃饱了撑的费这么大劲啊。那不是类成员变量定义时不准直接写赋值(C++11之前)吗。所以你在类体里定义成员变量时你只能写int &a,你不能写那个“=b” 啊。
这个初始化列表还有其他不得不用的情况,网上不乏相关资料,这里就不写了。