详解c++初始化列表,初始化列表的作用机理以及面试题

再谈默认构造函数

c++的默认构造函数有三种,分别是:不写编译器默认生成的,自己写的无参构造函数,自己写的全缺省构造函数
这个编译器默认生成有一个条件:自己必须一个构造函数都不写,否则编译器帮我们生成
不写构造函数不会报错,但是如果没有默认构造的话,就不能用如下方式创建对象。

Date d1(2022,8,20); //自己写的含参构造
Date d2; //调用默认构造函数

那么我们有没有其他方法来进行构造呢?于是c++引入了初始化列表

初始化列表

在这里插入图片描述
初始化列表就如上图所示,用:对函数进行初始化

初始化列表的意义

声明定义与初始化

一个变量有声明和定义两个过程。声明就是告诉计算机有这个变量,而定义就是开辟空间的过程。
而初始化可以被理解为是一种赋初值的过程。
而初始化列表可以认为是在定义的同时初始化。
传统的成员变量在对象实例化时定义,在构造函数初始化,那为什么要引入初始化列表呢?

初始化列表价值

因为有些成员变量他不能定义和初始化分离,比如const 修饰的变量,引用类型变量
在这里插入图片描述

在这里插入图片描述
可以看到直接赋值会报错,因为引用类型必须声明同时定义,如果没有初始化列表,成员对象直接在对象实例化时就声明了,没有定义的过程,所以报错了。
在这里插入图片描述
这样写就没有问题。

如果自定义对象作为成员属性时若没有默认构造,也需要初始化列表

我们先创建了一个没有默认构造函数的A类
在这里插入图片描述
再写一个以A实例化出对象为成员变量的对象B,默认构造函数中不写A的的构造函数,发现报错。
在这里插入图片描述
我们在初始化列表中手动调用a的带参构造就不会报错
在这里插入图片描述
而如果给A补上默认构造,也不会报错。
在这里插入图片描述

初始化列表的本质

前面我们讲过,在编译器生成的默认构造函数中,自定义类型会调用其对应的构造函数, 非自定义类型不初始化。
这是因为我们无论写不写初始化列表,编译器都会走一遍初始化列表。比如下面的代码

class Time
{
public:
 Time(int hour = 0)
 :_hour(hour)
 {
 cout << "Time()" << endl;
 }
private:
 int _hour;
};
class Date
{
public:
 Date(int day)
 {}
private:
 int _day;
 Time _t;
};
int main()
{
 Date d(1);
}

哪怕没写Time _t的初始化列表,编译器也会自动调用Time的构造函数

成员变量的声明次序就是初始化列表初始化次序

在这里插入图片描述
比如上面这个类,尽管_a先调用初始化列表,但实际上仍然是_aa先初始化。为随机值
在这里插入图片描述

隐式类型转换构造函数

在这里插入图片描述
先用10生成一个临时的A类对象,然后再利用A的拷贝构造使a完成对象实例化。
在这里插入图片描述
但是这样做会有很大问题,我们的单形参构造函数可能不允许我们这样做,于是c++引出了 explicit关键字

explicit关键字

构造函数不仅可以构造与初始化对象,对于单个参数的构造函数,还具有类型转换的作用。
在这里插入图片描述

用一个整形变量给A类型对象赋值
实际编译器背后会用10构造一个无名对象,最后用无名对象给a对象进行赋值。
但是我们给构造函数加上explicit 后就不允许这种隐式类型转换的构造方法。
在这里插入图片描述

隐式类型转换的优势

在后期我们会学String类,就可以用

string str1 = "abcdef";

来仅一步简化代码

总结

我们建议,能在初始化列表里初始化,就在初始化列表里初始化。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值