14-初始化列表

初始化列表

在以前,初始化成员变量是通过这种方式来进行的

struct Person {
    int m_age;
    int m_height;

    Person(int age, int height) {
        m_age = age;
        m_height = height;
    }
};
int main() {

    Person person(18, 180);
    getchar();
    return 0;
}

通过定义一个构造函数,然后再创建对象时,调用对应的构造函数时传入参数,在构造函数内部对成员变量进行初始化。初始化可以更便捷的方式来对成员变量进行初始化,初始化列表有以下特点:

  1. 一种便捷的初始化成员了变量的方式
  2. 只能用在构造函数中
  3. 初始化顺序只跟成员了变量的声明顺序有关

初始化列表的格式如下:

struct Person {
    int m_age;
    int m_height;
    Person(int age, int height) :m_age(age), m_height(height) {
    }
};

int main() {

    Person person(18, 180);
    cout << person.m_age << endl;
    cout << person.m_height << endl;
    getchar();
    return 0;
}

通过初始化列表的方式初始化成员变量与在构造函数中的方式初始化成员是等价的。并且通过程序运行的结果,也确实能达到与构造函数中初始化成员变量的目的。

证明初始化列表与普通初始化方式等价

如果将本文中第一段代码运行起来,然后看生成的汇编代码

通过生成的汇编代码,明显看到,分别有对m_age与m_height赋值。

然后,再将初始化列表初始化成员变量的方式运行起来,然后看生成的汇编代码

同样的,在这一段汇编代码中,同样看到了有对m_age与m_height赋值,并且生成的汇编指令是一样的。所以两种写法是完全等价的。对于初始化列表的这种方式,可以理解为是一种语法糖。

初始化列表中成员变量的初始化顺序

如果现在将初始化列表进行一些调整

struct Person {
    int m_age;
    int m_height;
    Person(int age, int height) :m_age(m_height), m_height(height) {
    }
};

int main() {

    Person person(18, 180);
    cout << person.m_age << endl;
    cout << person.m_height << endl;
    getchar();
    return 0;
}

最终打印出来的结果m_age是一堆乱七八糟的值,说明m_age并没有初始化,而且,如果将初始化列表中的m_age,m_height赋值顺序进行调换,也会出现一样的情况,说明在通过初始化列表初始化成员变量时,与初始化列表的赋值顺序无关。如果将成员变量的定义顺序调换以下, 最终得到的结果是两个成员变量都得到了初始化,所以需要注意初始化列表成员变量初始化顺序只与成员变量的定义顺序有关

默认参数与初始化列表的配合使用

利用前面的默认参数,与初始化列表结合的话,会起到什么样的效果呢?

struct Person {
    int m_age;
    int m_height;
    Person(int age = 0, int height = 0) :m_age(age), m_height(height) {
    }
};

int main() {

    Person person1;
    Person person2(17);
    Person person3(17,170);
    getchar();
    return 0;
}

通过默认参数,就可以选择在初始化的时候,是否设置成员变量的初始值,初始化对象时,更加方便。

构造函数的相互调用

有时候在编写程序时,有一种需求,在初始化对象时,需要将所有变量都初始化,但是有提供了多个构造函数,如果在每个构造函数都将成员变量单独初始化一遍的话,就会导致很多重复的代码,在这种情况下,就会考虑使用构造函数来调用其他构造函数初始化成员变量。

struct Person {
    int m_age;
    int m_height;
    Person(){
    
    }
    Person(int age, int height) {
        m_age = age;
        m_height = height;
    }
};

int main() {
    Person person;
    cout << person.m_age << endl;
    cout << person.m_height << endl;
    getchar();
    return 0;
}

如果现在想要调用无参的构造函数,并且最终创建出来对象的成员变量,都有初始值的话,你可能会想到在无参的构造函数里面调用有参的构造函数,即将代码修改为这样

Person(){
    Person(10,180);
}

如果这样调用的话,你会发现最终在获取创建出来对象的成员变量时,得到的值同样是乱七八糟的,说明通过这种方式成员变量并没有得到初始化。在构造函数章节里面讲到,构造函数被调用,就标志着一个新的对象被创建,说明这种方式是在无参构造函数里面创建了一个新的对象,并且在无参构造函数调用完毕后,就销毁了,对象的销毁,也可以通过析构函数得到证明。那应该怎样初始化呢?根据C++语法的要求,在构造函数相互调用时,只能构造函数放到初始化列表当中,所以需要修改为下面这种形式

Person() :Person(10,180){
}

将构造函数进行修改以后,最终可以看到,成功的通过构造函数调用了另外一个构造函数,并且成员变量也得到了初始化。

父类的构造函数

假设现在有两个类,存在继承关系

struct Person {
    int m_age;
    Person(){
        cout << "Person::Person()" << endl;
    }
    
    Person(int age){
        cout << "Person::Person()" << endl;
    }
};

struct Student :Person {
    int m_no;
    Student() {
        cout << "Student::Student()" << endl;
    }
};

int main() {
    Student student;
    getchar();
    return 0;
}

在创建子类兑现时,构造函数是如何调用的呢?将程序运行起来以后,看到的结果是先调用父类的构造函数,然后再调用当前类的构造函数。并且在默认情况下,会调用父类无参的构造函数,但是,如果子类的构造函数显式地调用了父类的有参构造函数,则就不会再去默认调用父类的无参构造函数。可以通过初始化列表的方式来调用父类其他构造函数

Student() :Person(10) {
    cout << "Student::Student()" << endl;
}

关于这些结论,都可以在程序运行起来时,通过汇编代码来查看。

如果父类没有无参的构造函数,则需要在子类显式的调用父类有参的构造函数,但是如果父类没有构造函数,则子类不用调用父类的构造函数。

demo下载地址

文章完。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容