C++的初始化列表(Initilization List)

        初始化类的成员有两种方式,一是使用初始化列表,二是在构造函数体内进行赋值操作。第二种我们都比较熟悉了,来看看第一种情况。
       一、 为什么使用初始化列表(Initialization list)
        使用初始化列表一方面主要是基于性能问题,对于类类型来说,最好使用初始化列表,为什么呢?
        因为对于没有默认构造函数的类类型,使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化。使用初始化列表少了一次调用默认构造函数的过程,这对于数据密集型的类来说,是非常高效的。
我们可以看一下实例:
#include<iostream>
#include <stdlib.h>
#include <string.h>
using namespace  std;
class Father
{
public:
	int x;
	int y;
	Father(int m=0,int n=0)
	{
		x=m;
		y=n;
		cout<<"this is constructor"<<endl;
	}
	Father(Father &fp)
	{
		this->x=fp.x;
		this->y=fp.y;
		cout<<"this is copy constructor"<<endl;
	}
	void  operator=(Father &f1)
	{
		this->x=f1.x;
		this->y=f1.y;
		cout<<"this is operator"<<endl;	
	}
	void show1()
	{
		cout<<x<<" "<<y<<endl;
	}
};
class Son
{
public:
	Father ff;
	int num;
	Son(Father f2,int number)
	{
		ff=f2;
		num=number;
		cout<<"this is son constructor"<<endl;
	}
	Son(int i,int j,int k):ff(i,j),num(k)
	{
		cout<<"this is son constructor for init list"<<endl;
	}
	void show2()
	{
		cout<<num<<endl;
	}
};
int main()
{
	Father f1(1,2);//不使用初始化列表来实现son的构造函数;
	Son s1(f1,44); 
        s1.ff.show1();
        s1.show2();
	system("pause");
	return 0;
}

当不适用初始化列表是实现son的构造函数时,其结果为:

C++的初始化列表(Initilization List)_第1张图片

        Son s1(1,2,44);  //使用初始化列表来实现son的构造函数;
        s1.ff.show1();
        s1.show2();

当使用初始化列表实现son的构造函数时,其结果为:

C++的初始化列表(Initilization List)_第2张图片

由结果对比可明显知道省去了调用默认构造函数的过程,提高了程序的运行效率。所以一个好的原则是,能使用初始化列表的时候尽量使用初始化列表。

二、另一方面,有些成员变量的初始化必须放在初始化列表里。哪些东西必须放在初始化列表中呢?

    构造函数初始化时必须采用初始化列表一共有三种情况,

        1. 没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数初始化(实例一可说明)。
        2.需要初始 化const修饰的类成员;(因为const的成员不能改变所以不能对其进行复制,只能对其进行初始化)
        3.需要初始 化引用成员数据;(引用一开始必须初始化,并且已经初始化的引用不能再变)
        2、3两点可以通过下面实例来解释:
class Father
{
public:
	const  int x;  //常量变量
	int &y;   //引用变量;
	/*Father(int n=1)  //此种初始化方法会报错;
	{
	   x=n;  
	   y=x;
	}*/
	Father(int m,int n):x(m),y(n)  //必须的这样初始化;
	{  
	}
};
三、成员变量的初始化顺序
    成员是按照他们在类中出现的顺序进行初始化的,而不是按照他们在初始化列表出现的顺序初始化的,看代码。
class Father
{
public:
	int x;
	int y; 
	Father(int m):x(m),y(n){};  //OK 先初始化x,再初始化y;
};
   再看下面的代码
class Father
{
public:
	int x;
	int y; 
	Father(int m):x(y),y(m){};  //这里的x的值是未定义的;
};
  这里x的值是未定义的,虽然x在初始化列表里面出现在y前面,但是x先于y定义,所以先初始化x,但x由y初始化,此时y尚未初始化,所以导致x的值未定义。

  所以,一个好的习惯是,按照成员定义的顺序进行初始化。



你可能感兴趣的:(初始化列表,常量成员的初始化,引用成员的初始化)