1. 程式人生 > >C++的初始化列表(Initilization List)

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的建構函式時,其結果為:


        Son s1(1,2,44);  //使用初始化列表來實現son的建構函式;
        s1.ff.show1();
        s1.show2();

當使用初始化列表實現son的建構函式時,其結果為:


由結果對比可明顯知道省去了呼叫預設建構函式的過程,提高了程式的執行效率。所以一個好的原則是,能使用初始化列表的時候儘量使用初始化列表。

二、另一方面,有些成員變數的初始化必須放在初始化列表裡。哪些東西必須放在初始化列表中呢?

    建構函式初始化時必須採用初始化列表一共有三種情況,

      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的值未定義。

  所以,一個好的習慣是,按照成員定義的順序進行初始化。