C++學習 對象模型之細談成員初始化列表

直接上代碼

上面紅色框起來的部分就是類成員初始化列表,成員初始化列表一般用在類的構造函數中,包括拷貝構造函數。對於這種用法,作爲C++程序員一點都不陌生。下面從幾個疑惑開始講解,成員初始化列表:

1.什麼時候必須要使用初始化列表

(1)初始化成員有引用

以上代碼編譯器會報錯,編譯器不允許這樣初始化,至於爲什麼不允許,後面再探討,只能按照一下方式來初始化引用成員數據

這樣編譯器就不會報錯了

(2)初始化const類型成員

這樣初始化const 類型成員編譯器會報錯,至於編譯器爲什麼會允許這樣做,還沒明白。按照以下做法就不會報錯

 

(3)類繼承於一個父類,且父類含有有參數的構造函數

(3)含有類成員變量,且類成員的構造函數有參數

 

2.爲什麼要使用成員初始化列表,答案是爲了提高程序的效率

既然發明了這個語法,一定有一定的道理,且一定有利於程序的運行。以下代碼可以非常清晰的說明:

class A {
public:
    int m_a;
    int m_b;
    A(){
        cout << "A 的構造函數" << endl;
    }
    A(int tmp):m_a(tmp),m_b(tmp) {
        cout << "A 的拷貝構造函數" << endl;
    }
    ~A() {
        cout << "A 的析構函數" << endl;
    }

};
class B  {
public:
    int tt_a;
    int tt_b;
    A m_aobj;
    B(int a, int b) : tt_a(a), tt_b(b) {
        m_aobj = a;

        cout << "B 的構造函數" << endl;
    }
    ~B() {
        cout << "B 的析構函數" << endl;
    }

};

int main()
{
    //A a_obj1(10,20);
    B b(10, 20);
    std::cout << "Hello World!\n";
    return 0;
}

這時候m_aobj 成員我們沒有用初始化列表來初始化,運行結果爲

 

如果m_aobj換成在初始化列表中初始化,如下代碼

class B  {
public:
    int tt_a;
    int tt_b;
    A m_aobj;
    B(int a, int b) :m_aobj(a), tt_a(a), tt_b(b) {
        //m_aobj = a;

        cout << "B 的構造函數" << endl;
    }
    ~B() {
        cout << "B 的析構函數" << endl;
    }

};

運行結果就變成

 

很明顯的看到後者少調用了一次A的構造函數和一次析構函數。因爲前者編譯器會生成一個臨時對象。由此說明成員初始化列表優化程序運行效率。

 

(3)使用成員初始化列表需要注意哪些細節

(1)成員初始化列表會被編譯器轉換爲代碼並被放在用戶代碼之前。‘

(2)成員的初始化並不是按照初始化列表的順序來的,而是按照成員在類的定義順序來初始化

class A {
public:
    int m_a;
    int m_b;
    A(int a):m_a(a){
        cout << "A 的構造函數" << endl;
    }
    ~A() {
        cout << "A 的析構函數" << endl;
    }

};
class B  {
public:
    int tt_a;
    int tt_b;
    B(int a, int b) : tt_a(a), tt_b(b) {
        //m_aobj = a;

        cout << "B 的構造函數" << endl;
    }
    ~B() {
        cout << "B 的析構函數" << endl;
    }

};

class C {
public:
    A aa;
    B bb;
    C(int a) :bb(a,a), aa(a) {
        cout << "C 的構造函數" << endl;
    }

};

int main()
{
    //A a_obj1(10,20);
    C c(10);
    std::cout << "Hello World!\n";
    return 0;
}

這裏我們的初始化列表順序是 B A,定義順序是A B。運行結果如下

顯然是按照定義的順序來初始化的,而不是初始化列表順序。

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章