class Array {
std::vector data_;
int size_;
int lbound_, hbound_;
public:
Array(int low, int high)
: size_(high - low + 1),
lbound_(low), hbound_(high),
data_(size_) {} // 看似正確
};
int main() {
Array a(0, 10);
std::cout << a.size() << ' ' << a.data().size(); // 輸出:11 18446744073709551615 (或其他巨值)
}
**成員初始化順序严格遵循類中聲明順序**,與初始化列表書寫順序無關。
類中聲明順序:
std::vector data_; // 第1個
int size_; // 第2個
int lbound_, hbound_; // 第3、4個
實際執行順序:
data_(size_) —— 此時 size_ **未初始化**,值不定;size_(...);lbound_(...), hbound_(...)。// 方法一:聲明順序優先
class Array {
int size_;
int lbound_, hbound_;
std::vector data_; // 最後聲明
public:
Array(int low, int high)
: size_(high - low + 1),
lbound_(low), hbound_(high),
data_(size_) {} // 現在 size_ 已初始化
};
// 方法二:聲明順序不變,列表按聲明順序寫(編譯器會重排,但可讀性差)
Array(int low, int high)
: data_(high - low + 1), // 直接用表達式,不依賴 size_
size_(high - low + 1),
lbound_(low), hbound_(high) {}
**析構順序必須與構造順序完全相反**。若允許按列表順序構造,編譯器需為每個對象記錄構造順序以正確析構,帶來巨大開銷(隱藏數組/鏈表)。統一聲明順序,編譯器只需按固定偏移調用析構函數,零開銷。
-Wreorder (GCC/Clang) / /Wall (MSVC)開啟警告,編譯器會提示初始化列表順序與聲明順序不一致。
初始化列表看似簡單,**成員聲明順序決定初始化順序**是 C++ 核心規則之一。養成「先聲明被依賴成員,再聲明依賴成員;列表按聲明順序寫」的習慣,能杜絕此類難以調試的「亂碼」Bug。