C++的初始化列表(Initilization List)
阿新 • • 發佈:2018-12-30
初始化類的成員有兩種方式,一是使用初始化列表,二是在建構函式體內進行賦值操作。第二種我們都比較熟悉了,來看看第一種情況。
一、 為什麼使用初始化列表(Initialization list)
使用初始化列表一方面主要是基於效能問題,對於類型別來說,最好使用初始化列表,為什麼呢?
因為對於沒有預設建構函式的類型別,使用初始化列表可以不必呼叫預設建構函式來初始化,而是直接呼叫拷貝建構函式初始化。使用初始化列表少了一次呼叫預設建構函式的過程,這對於資料密集型的類來說,是非常高效的。
我們可以看一下例項:
當使用初始化列表實現son的建構函式時,其結果為:
2.需要初始化const修飾的類成員;(因為const的成員不能改變所以不能對其進行復制,只能對其進行初始化)
3.需要初始化引用成員資料;(引用一開始必須初始化,並且已經初始化的引用不能再變)
2、3兩點可以通過下面例項來解釋:
成員是按照他們在類中出現的順序進行初始化的,而不是按照他們在初始化列表出現的順序初始化的,看程式碼。
一、 為什麼使用初始化列表(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的值未定義。所以,一個好的習慣是,按照成員定義的順序進行初始化。