在C++中,

#include <iostream>
using namespace std;

struct Data{
    int x = 10;
    int y() { return 20; }     
};

int main()
{
    Data* p=NULL;  // 不用 new 建立指標
    cout<<p->x<<endl;  //丟擲異常
    cout<<p->y()<<endl; //程式能正常輸出20
    return 0;
}

這是因為,成員函式是屬於類的,而成員變數是屬於物件的。
成員函式和普通函式沒有本質什麼區別,都是直接呼叫函式的,只是比普通函式多了一個 this 指標而已。如果成員函式裡面沒有使用這個 this 指標(也就是沒有使用任何成員變數),那麼 this 指標的值為多少就無所謂了,不管他是隨機值或是 NULL.
只用通過指標呼叫虛擬函式才會通過物件的虛擬函式表去查詢函式的地址,這時指標無效就會出問題了。
在上面程式碼中,int* p;到底有沒有在堆空間開闢一個4位元組大小的記憶體空間呢?
沒有,這是在棧內定義的一個指標,所以是在棧內開闢了一個4位元組大小的記憶體空間(用來放指標變量了)。
與此對應的,int* p = new int;是在棧上開闢了4個位元組放指標,又在堆上開闢了4個位元組(準備)放int變數

函式之所以會呼叫成功,是因為利用指標呼叫類的成員函式時,只跟指標的型別有關,而與其所指內容無關,也就是說只要指標型別是這個類的指標,那就可以用它來呼叫這個類的成員函式。如果這個函式做的事情跟類物件無關,就像你只返回一個常數,那這個函式看起來是正常執行的,但如果在類裡訪問了類的成員變數(比如返回x),那就會出錯,因為此時要根據指標所指的內容去訪問對應的成員變數,而指標實際上沒有指向正確的地方,所以會出現記憶體訪問錯誤。