【C++】初始化列表的意义

前言


  • 🚄 输入是学习的本质,输出是学习的手段。
  • 🔖 分享每一次的学习,期待你我都有收获。
  • 🎇 欢迎🔎关注👍点赞⭐️收藏✉评论,共同进步!
  • 🌊 “要足够优秀,才能接住上天给的惊喜和机会”
  • 💬 博主水平有限,如若有误,请多指正,万分感谢!

初始化列表

用法:

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。

探讨初始化列表,就能明白成员变量是什么时候被创造出来的。

初始化列表用于构造函数,可以用来对成员变量进行初始化

我们先创建一个日期类:

class Date
{
public:
	void Print()  //打印
	{
		cout << _year << " - " << _month << " - " << _day << endl;
	}

	Date(int year = 0, int month = 1, int day = 1,int capacity = 4)
	{
		_year = year;
		_month = month;
		_day = day;
	}

private:
	int _year;
	int _month;
	int _day;
};

int main()
{

	return 0;
}

现阶段,我们最熟悉的初始化方法是这样的:

Date(int year = 0, int month = 1, int day = 1,int capacity = 4)
{
	_year = year;
	_month = month;
	_day = day;
}

运用初始化列表我们可以这样写:

Date(int year = 0, int month = 1, int day = 1):_year(year),_month(month),_day(day)
{
	;
}

那有些同学就要有疑问了,这不是吃饱了没事找事吗?

这样写既麻烦也没有第一种简洁明了为什么还要用

不急,我们再来看这样一组代码对比:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rIRa7Nhb-1646462952310)(C:\Users\Z-zp\AppData\Roaming\Typora\typora-user-images\image-20220202221316140.png)]

注意:这里我又给 _year 赋值了一遍,所以编译器给我报错了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NHD9Qrjd-1646462952310)(C:\Users\Z-zp\AppData\Roaming\Typora\typora-user-images\image-20220202221404077.png)]


但是如果我是用第一种方法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SeR2H6Qt-1646462952310)(C:\Users\Z-zp\AppData\Roaming\Typora\typora-user-images\image-20220202221613294.png)]

编译器完全不报错,这里已经暗示这两种方法其实是有区别的。


如果我们在成员变量中加点不一样的成员,初始化列表的作用就能体现出来了。

class Date
{
public:
	void Print()  //打印
	{
		cout << _year << " - " << _month << " - " << _day << endl;
	}

	Date(int year = 0, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
		_n = 10;
	}

private:
	int _year;
	int _month;
	int _day;
	const int _n; //加个const修饰的成员
};

int main()
{

	return 0;
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kyqFygAi-1646462952311)(C:\Users\Z-zp\AppData\Roaming\Typora\typora-user-images\image-20220202222632549.png)]

这里的意思就是,_n必须用初始化列表初始化。


我们再看一个例子,一会儿一起解释。

	int _year;
	int _month;
	int _day;
	const int _n;  //加个const修饰的成员
	int& ret;  //再加个引用类型

我们说引用类型必须初始化,可是类只是一个类似模板一样的东西,在类里无法初始化(缺省值≠初始化)。

那ret怎么初始化?是否无法完成初始化?

	Date(int year = 0, int month = 1, int day = 1,int& b)
	{
		_year = year;
		_month = month;
		_day = day;
		_n = 10;
        ret = b;
	}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tDI4bQAf-1646462952311)(C:\Users\Z-zp\AppData\Roaming\Typora\typora-user-images\image-20220202223952817.png)]


如果我们使用的是初始化列表,程序就不会报任何错误

	Date(int& b,int year = 0, int month = 1, int day = 1)
		:_year(year),
		_month(month),
		_day(day),
		_n(10),
		ret(b)
	{
		;
	}

到此我们就可以理解了:

类只是对成员变量、成员函数的声明,声明和定义有时是分开的,就像是

int x; //初始化为随机值
x=10; //这里已经不是初始化了,而是赋值。

初始化列表的作用,就是对类成员变量进行初始化

无论是内置类型也好,自定义类型也好,显然,初始化只会进行一次

因此才会出现这样的错误
在这里插入图片描述在这里插入图片描述

初始化两次是不可以的。


题外话:新版本的C++是支持这种写法的——在类里给成员变量赋值,但是这样的本质是给缺省值

证据是,如果我们在实例化对象时传实参给构建函数,可以调用初始化列表初始化,

并且最后得到的日期依然是我们传的日期。

class Date
{
public:
    
	Date(int year = 0, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
		_n = 10;
	}

private:
	int _year = 10;
	int _month = 1;
	int _day = 1;
	const int _n; //加个const修饰的成员
};

总结:在类中,对于一些特殊的成员变量——必须在声明的同时初始化,有两种解决方法:

  1. 初始化列表初始化
  2. 给缺省值初始化

注:成员变量初始化的顺序与其在初始化列表中出现的顺序无关,只由声明的先后顺序有关。

先声明,先初始化


样例:

下面程序的运行结果是( )class A
{
public:

    A(int a) :_a1(a), _a2(_a1)
    {
        ;
    }

    void Print()
    {
        cout << _a1 << " " << _a2 << endl;
    }

private:

    int _a2;

    int _a1;

};


int main()
{
    A aa(1);

    aa.Print();
}

因为_a2先声明,所以先初始化 _ a2=_a1,此时的 _a1因为还没初始化,所以 _a2是随机值

然后才是 _a1= a

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿波呲der

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值