1. 程式人生 > >【校招面試 之 C++】第1題 為什麽優先使用構造函數的初始化列表

【校招面試 之 C++】第1題 為什麽優先使用構造函數的初始化列表

初始化 校招 操作 struct st2 使用 mage div 賦值運算

1.首先看一個例子:

#include<iostream>
using namespace std;


class Test1
{
public:
    Test1() // 無參構造函數
    { 
        cout << "Construct Test1" << endl ;
    }

    Test1(const Test1& t1) // 拷貝構造函數
    {
        cout << "Copy constructor for Test1" << endl ;
        this->a = t1.a ;
    }

    Test1& operator = (const Test1& t1) // 賦值運算符
    {
        cout << "assignment for Test1" << endl ;
        this->a = t1.a ;
        return *this;
    }
private:
    int a ;
};

class Test2
{
public:
    Test1 test1 ;
	// 情形1:不使用初始化參數列表
//Test2(Test1 &t1) //{ // test1 = t1 ; //} // 情形2:使用初始化參數列表 Test2(Test1 &t1):test1(t1){} }; int main(){ Test1 t1; Test2 t2(t1); system("pause"); return 0; }

情形1輸出:

技術分享圖片

情形2輸出:

技術分享圖片

第二種情況輸出對應Test2的初始化列表,直接調用拷貝構造函數初始化test1,省去了調用默認構造函數的過程。所以一個好的原則是,能使用初始化列表的時候盡量使用初始化列表。提高了性能。

2. 除了性能問題之外,有些時場合初始化列表是不可或缺的,以下幾種情況時必須使用初始化列表

  • 常量成員,因為常量只能初始化不能賦值,所以必須放在初始化列表裏面
  • 引用類型,引用必須在定義的時候初始化,並且不能重新賦值,所以也要寫在初始化列表裏面
  • 沒有默認構造函數的類類型,因為使用初始化列表可以不必調用默認構造函數來初始化,而是直接調用拷貝構造函數初始化。

對於沒有默認構造函數的類,我們看一個例子。

struct Test1
{
    Test1(int a):i(a){}
    int i ;
};

struct Test2
{
    Test1 test1 ;
    Test2(Test1 &t1)
    {
        test1 = t1 ;
    }
};

以上代碼無法通過編譯,因為Test2類中Test1 test1;需要調用默認的構造函數,但是Test1類沒有無參的構造函數,但是由於Test1沒有默認的構造函數,故而編譯錯誤。正確的代碼如下,使用初始化列表代替賦值操作。

struct Test2
{
    Test1 test1 ;
    Test2(Test1 &t1):test1(t1){}
}

成員變量的初始化順序

成員是按照他們在類中出現的順序進行初始化的,而不是按照他們在初始化列表出現的順序初始化的,看代碼。

struct foo
{
    int i ;
    int j ;
    foo(int x):i(x), j(i){}; // ok, 先初始化i,後初始化j
};

【校招面試 之 C++】第1題 為什麽優先使用構造函數的初始化列表