C++ 學習 對象模型之類及對象內存模型

使用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指針就可以訪問對象其他數據成員。換句話說,我們定義的成員函數,編譯器會給我們轉換成另一種形式。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章