建構函式擁有特殊的初始化語法——初始化列表,位於參數列表之後、函式本體 {} 之前。列表中的初始化動作會在函式本體任何程式碼執行前完成。
class A { public: A(int x); };
class B : public A {
public:
B(int x, int y);
};
B::B(int x, int y) : A(x) { // 在初始化列表呼叫 A 的建構函式
// ...
}
const 資料成員只能在初始化列表初始化:因為它們不可在函式本體以指派方式賦值(參見第 5.4 節)。對於非內建型別(類別型別)的成員物件,必須使用初始化列表以獲得更高效率。
class A {
A(); A(const A&); A& operator=(const A&);
};
class B {
public:
B(const A& a);
private:
A m_a;
};
// 寫法 (a):初始化列表 —— 呼叫 A 的複製建構函式,一次到位
B::B(const A& a) : m_a(a) { ... }
// 寫法 (b):函式本體指派 —— 隱含兩步動作:
// 1. 暗中建立 m_a(呼叫 A 的預設建構函式)
// 2. 呼叫 A 的指派運算子將 a 指派給 m_a
B::B(const A& a) {
m_a = a; // 實際上執行了「預設建構 + 指派」兩步
}
寫法 (a) 直接呼叫複製建構函式,避免多餘的預設建構與指派開銷,效率顯著更高。
對於 int、float 等內建型別,兩種寫法效率差異可忽略,但函式本體指派的程式碼風格較清晰:
class F {
public:
F(int x, int y);
private:
int m_x, m_y, m_i, m_j;
};
// 初始化列表寫法
F::F(int x, int y) : m_x(x), m_y(y) {
m_i = 0; m_j = 0;
}
// 函式本體指派寫法
F::F(int x, int y) {
m_x = x; m_y = y;
m_i = 0; m_j = 0;
}
最佳實踐建議:類別型別成員用初始化列表;內建型別成員視團隊風格統一,推薦函式本體指派以提升可讀性。