首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

C++對象模型深度解析:成員初始化列表(第二章 2.4)

     編輯:關於C++

何時必須使用成員初始化列表?

以下四種情況只能在初始化列表中完成,無法在構造函數體內賦值:

  1. 初始化引用類型成員(Reference member)。
  2. 初始化const 常量成員。
  3. 調用基類帶參數的構造函數。
  4. 調用成員類對象帶參數的構造函數。

效率差異:賦值 vs 初始化列表

// 低效寫法:構造函數體內賦值
class Word {
    String _name;
    int _cnt;
public:
    Word() { _name = 0; _cnt = 0; } // 產生臨時對象、拷貝、銷毀
};

// 高效寫法:初始化列表
Word::Word() : _name(0) { _cnt = 0; } // 直接調用 String(int) 構造

編譯器會將初始化列表展開為構造函數體開頭的成員構造調用,避免預設構造 + 賦值 + 析構的額外開銷。

初始化順序陷阱

成員初始化順序由類中聲明順序決定,而非初始化列表中的書寫順序。

class X {
    int i;
    int j;
public:
    X(int val) : j(val), i(j) {} // 危險!i 先初始化,但 j 尚未賦值
};

上例中 i 會被初始化為不可預測的垃圾值。編譯器應發出警告(如 g++),但 MSVC 可能不警告。

初始化列表與構造函數體的執行順序

  • 初始化列表項目按聲明順序插入構造函數體最前面。
  • 隨後執行用戶編寫的構造函數體代碼。
  • 因此 X(int val) : j(val) { i = j; } 是安全的,因為 j 的初始化先於 i = j。

在初始化列表中調用成員函數

合法,因為 this 指針已就緒。但建議謹慎使用,避免依賴尚未初始化的其他成員。

X::X(int val) : i(xfoo(val)), j(val) {} // xfoo 為成員函數
// 展開為:i = this->xfoo(val); j = val;

總結

  • 編譯器按聲明順序處理初始化列表,插入構造函數體最前端。
  • 優先使用初始化列表,特別是對類類型成員、const、引用、基類構造。
  • 避免在列表中使用尚未初始化的成員作為參數。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved