【C++】之类和对象 - 初始化列表

发布于:2023-01-21 ⋅ 阅读:(436) ⋅ 点赞:(0)

目录

一.初始化列表的本质

二.使用初始化列表


引出:对象在被编译器创建出来时,编译器给对象开辟好空间,那么对象中的成员变量是何时被定义的呢?编译器在创建对象时,会自动调用构造函数,调用构造函数的本质是什么?

一.初始化列表的本质

class Time
{
public:
	//显示定义一个有参的构造函数,运行报错
	Time(int hour)
	{
		_hour = hour;
	}
	//显式定义一个全缺省的默认构造函数,运行可以通过
	//Time(int hour = 0)
	//{
	//	_hour = hour;
    //  cout << "调用Time全缺省构造" << endl;
	//}
private:
	int _hour;
};
class Date
{
public:
	Date(int year, int month, int day, int hour)
	{
		_year = year;
		_month = month;
		_day = day;
		Time t(hour);
		_t = t;
	}
private:
	int _year;
	int _month;
	int _day;
	Time _t;
};
int main()
{
	Date d1(2022, 8, 10, 24);
	return 0;
}

结果:报错

默认构造分三类:编译器生成,显式定义无参,显式定义全缺省

这里报错的原因:Date的构造函数对于内置类型不做处理,对于自定义类型调用其自己的默认构造函数,可以看到,由于Time类中我们显示写了有参构造,编译器就不会生成,自然就没有默认构造。如果我们用int hour = 0这样全缺省的构造就可以被调用了并且调用之后是我们想要的结果。

通过这一现象,可以进一步思考,为什么一定要调用默认构造?我显示定义的有参构造难道不可以直接调用吗?这时需要引出初始化列表这一概念。回到了最开始的问题,对象内的成员变量究竟是何时被定义的? 

Time的全缺省构造是被调用了两次的。因为Time的全缺省构造既是默认构造,又是有参构造。

这里就解释了为什么一定要调用默认构造!每个构造函数都隐式的拥有一个初始化列表,而对象内的成员变量就是在初始化列表中被定义的

以上这里的调用逻辑是:

---> 编译器先创建一个Date类的对象d1,编译器自动调用Date构造函数

这时(构造函数对内置类型不处理,对自定义类型调用自己的默认构造函数)本质就是在初始化列表中给定义的成员变量初始化,由于我们不显式的去写的话,也就没有参数,只能是隐式的调用默认构造函数,也就不需要参数。

---> 初始化列表调用一次默认构造函数(也就是Time的全缺省构造)

---> 之后在Time t(hour)时,再调用一次Time全缺省构造

可以看到对于自定义类型的成员变量类内初始化时:

        1.会调用两次构造 + 一次拷贝

(一次在初始化列表调用,一次在创建临时变量调用,一次临时变量的拷贝)

        2.自定义类型一定要有自己的默认构造

        3.代码过于繁琐

对于以上的总结:

1.初始化列表可以认为是成员变量定义的地方

2.类内初始化成员变量,其实严格意义上不是初始化而是赋值,因为成员变量在初始化列表被定义,被定义的同时也就被初始化了。

3.对于内置类型在哪里初始化都行,对于自定义类型推荐使用初始化列表

二.使用初始化列表

class Time
{
public:
	Time(int hour)
	{
		_hour = hour;
	}
private:
	int _hour;
};
class Date
{
public:
	Date(int year, int month, int day, int hour)
		:_year(year),_month(month),_day(day),_t(hour)
	{

	}

private:
	int _year;
	int _month;
	int _day;
	Time _t;
};
int main()
{
	Date d1(2022, 8, 10, 24);
	return 0;
}

注意

1.每个变量只能在初始化列表出现一次

2.以下成员必须在初始化列表初始化

        引用成员变量

        const成员变量

        自定义类型成员变量(没有默认构造时)

引用与const成员变量有一个共同特点:必须在变量定义的地方初始化!而不能定义之后再赋值!

而自定义类型成员变量在初始化列表隐式定义时必须调用默认构造

3.成员变量定义的顺序不是初始化列表中的顺序,而是在类中声明的顺序

4.由于C++默认构造对于内置类型不做处理而有可能导致为随机值,之后打了一个补丁,在变量声明的地方可以加缺省值,这个补丁的本质就是在初始化列表给内置类型加上默认值


网站公告

今日签到

点亮在社区的每一天
去签到