使用C++開發一年多,從今天開始系統性的總結下C++一些知識點,畢竟C++語言特性複雜而龐大,很難短時間全部掌握。
1.類及對象
首先類可以類比C語言的struct結構體,單純的聲明一個類A,如果A沒有被實例化,那麼A是不會佔用內存空間。這裏的類可以理解爲一種特殊數據結構類型。再來談談對象,一個類實例化後就變成一個對象,且對象活躍在內存中。在這裏的對象可以理解爲C語言的變量。C語言中定義一個結構體變量,就是在內存中開闢一段空間來存儲結構體,那麼這段內存就是變量。類被實例化,本質也是在內存開闢一段空間來存儲類,這段內存空間就叫對象。
2.對象的內存分佈模型
C++對象模型已經經過多年的發展,在這裏只介紹當前的C++對象內存模型。
class A{
public:
int a;
static double b;
void fun1(){};
virtual void fun2(){};
virtual void fun3(){};
}
在這裏定義了一個類A,那麼如果 A a;實例化A生成對象a,那麼sizeof(a)是多大呢?
在對象的內存結構中,只有非靜態數據成員和指向虛函數表的指針佔用對象內存。其中虛函數會被記錄在一個虛函數表裏面。
由此推斷sizeof(a)是8字節,其中只有a和虛函數指針存在於對象內存。
其中靜態數據成員是所有對象共享
疑惑:實例化類A產生對象a,這個步驟開闢了多少內存,如果只分配了8字節,那麼當對象a調用非靜態成員函數時,這些東西內存裏面都沒有,因此類成員函數一定會被放入內存,那麼這個步驟又是什麼時候發生的呢?
猜測:每個對象都有自己唯一的非靜態成員函數,但這些非靜態成員函數不會被放到對象內存佈局中,而是被放到了另外一段內存裏面,因此實例化類A這個步驟其實並不僅僅開闢了8字節內存,這裏只是猜測,後續學習遇到再驗證。
最終結論:類的所有含有成員函數包括靜態成員函數,在程序載入時都放到了內存代碼區,所以以上實例化A內存就分配了8字節。
每個類的成員函數在內存只會存在一份,成員函數都是類似這樣A::fun1,下面給出實際調試例子:
反彙編後如下
可以看到不同對象調用相同成員函數,成員函數的地址都是一個。實際上對象再調用成員函數的時候會把this指針傳到成員函數中。經過編譯器處理後,成員函數可能會被定義成 void A::fun1(A *p) ,這裏的p就是this指針,根據這個this指針就可以訪問對象其他數據成員。換句話說,我們定義的成員函數,編譯器會給我們轉換成另一種形式。