在 C++ 中,通過空指針調用成員函數若不訪問成員變量,竟然不會崩潰。例如:
Test *t = NULL;
t->funcMember(); // 若 funcMember 內不使用 this,則正常執行
成員函數編譯後實際為:
void funcMember(Test* const this)
調用時將對象地址作為第一個參數傳入。只要函數體內不解引用 this(即不訪問成員變量),空指針也能「安全」執行。
反汇編可見調用指令為 CALL Test::funcMember,參數通過 ECX/RCX 或棧傳遞對象地址。若不解引用,CPU 不會訪問該地址內存,故不觸發段錯誤。
示例代碼通過 reinterpret_cast 將 this 強轉為 int*,逐個輸出對象內存佈局,觀察成員變量分佈及填充字節。發現對象實例在棧上佔用連續內存,成員按聲明順序排列,編譯器可能插入填充對齊。
class Test {
public:
void funcMember() {
int *ptr = reinterpret_cast(const_cast(this));
cout << *ptr << endl; // 輸出第一個 int 成員 x
ptr += 3; // 跳過填充/其他成員
cout << *ptr << endl;
}
Test(): x(3) {}
int x;
};
int main() {
Test tt;
tt.funcMember();
}