【C++】深入探索构造函数---初始化列表

·1.初始化列表是什么
·2.使用初始化列表更高效,为什么?
·3.哪些成成员变量必须放在初始化列表里?
·4.成员变量按声明顺序初始化,而不是初始化列表。
·5.声明和定义的区别
·6.那些类必须自己写构造函数

类的成员变量有俩种初始化方式:1.初始化列表。2.构造函数体内进行赋值。

之前使用的初始化方式是第二种,那么第一种方式初始化列表是什么呢?

1.初始化列表是什么?初始化列表是以一个冒号开始,接着一个逗号分隔数据列表,每个数据成员都放入一个括号中进行初始化。

2.使用初始化列表更高效,为什么呢?尽量使用初始化列表进行初始化,因为这样子更加高效,为什么更加高效呢?先写一段代码。

class Time
{
public:
	Time()
	{
		cout<<"Time()"<<endl;
		_hour = 0;
		_minute = 0;
		_second = 0;
	}
	Time(const Time& t)
	{
		_hour = t._hour;
		_minute = t._minute;
		_second = t._second;
	}
private:
	int _hour;
	int _minute;
	int _second;
};

class Date
{
public:
        //【1】
	Date(int year,int month,int day,const Time& t)
	{
		cout<<"Date()非初始化列表"<<endl;
		_year = year;
		_month = month;
		_day = day;
		_t = t;
	}
        //【2】
	Date(int year,int month,int day,const Time& t)
		:_year(year)
		,_month(month)
		,_day(day)
		,_t(t)
	{
		cout<<"Date()初始化列表"<<endl;

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

void newTest()
{
	Time t1;
	Date d1(2018,9,30,t1);
}

运行结果:

【1】可以试着猜猜他的运行结果,按照之前所学到的知识也许会猜测运行结果应该是Time()  Date()...emmmm到底正不正确呢让我们一起来看看:

运行后,会发现结果比猜测的多了一个Time()Time类的构造函数,这个构造函数是哪里来的呢?通过调试就会发现在非初始化列表Date(int year,int month,int day,const Time& t)与{之间多了一次Time(),其实这里有一个初始化列表但是我们自己没有写,初始化列表不写,编译器也会自动初始化,这个针对的是自定义类型:Time。

下来我们来看看写了初始化列表后的运行结果:

通过对比就会发现,使用初始化列表比不使用初始化列表少调用了一次Time的构造函数,因此使用初始化列表更加高效。初始化列表可以认为是成员变量定义的地方。

3.哪些成员变量必须放在初始化列表里面?

3.1.常量成员变量。(常量创建时必须初始化)----必须要在定义时给一个初始值,之后不可以改变。

3.2.引用类型成员变量。(引用创建时必须初始化)--一个别名,在定义时必须初始化。

3.3.没有缺省构造函数的成员变量

用一段代码对上面三种成员变量进行测试:

class Time
{
public:
	/*Time()
	{
		cout<<"Time()"<<endl;
		_hour = 0;
		_minute = 0;
		_second = 0;
	}*/
	Time(const Time& t)
	{
		_hour = t._hour;
		_minute = t._minute;
		_second = t._second;
	}
private:
	int _hour;
	int _minute;
	int _second;
};

class Date
{
public:
	Date(int year,int month,int day,const Time& t)
		:_year(year)
		,_month(month)
		,_day(day)
		,_t(t)
	{

	}
private:
	int _year;
	int _month;
	int _day;
	const int _testConst;    //测试const成员变量的初始化
	int& _testReFerence;        //测试引用成员变量的初始化
	Time _t;              //测试无缺省(不传值)构造函数的自定义类型成员变量的初始化
};

void newTest()
{
	Time t1;
	Date d1(2018,9,30,t1);
}

编译代码会发现编译器报错:

通过测试证明结论正确。

4.成员变量按声明顺序初始化,而不是初始化列表。

运行下面代码:

class Date
{
public:
	Date(int x)
		:_day(x)
		,_month(_day)
		,_year(x)
	{}

	void Display()
	{
		cout<<"year:"<<_year<<endl;
		cout<<"month:"<<_month<<endl;
		cout<<"day:"<<_day<<endl;

	}
private:
	int _year;
	int _month;
	int _day;
};
void newTest()
{
	Date d1(1);
	d1.Display();
}

来猜猜这段代码运行结果是什么》》》》是 1 1 1么?让我们一起来看看

通过结果发现,很显然不是我们猜测的 1 1 1,它的month竟然是一个随机值,为什么呢?因为

成员变量按声明顺序初始化,而不是初始化列表。所以_day的初始化在_month之后,将_day赋值给_month就是将一个随机值付给了_month,因此就会出现我们所看到的结果。

5.声明和定义的区别:

  声明:我告诉编译器我要定义它;

  定义:定义时开辟空间。

6.那些类必须自己写构造函数:类中有const类型的成员变量。

猜你喜欢

转载自blog.csdn.net/hgelin/article/details/82908613