類 物件的記憶體模型

2021-04-30 13:03:03 字數 1640 閱讀 4898

原問題如下:

#include

using namespace std;

class base

void fun2()

};int main()

**的結果為4。

這個我覺得是因為那個虛函式表裡的乙個指標佔了4個位元組

但是如果我去掉virtual **的結果為1

類中的普通成員函式佔物件的空間嗎?資料成員所佔空間的計算是否也是和結構體類似呢?

這個就不明白了,請各位指點。。

我的回答如下:

這個涉及到類和結構體,在c++內部的排列方式。

我們知道,c和c++雖然都支援結構體,但是,實際上表現是不一樣的。c++的結構體,可以認為是類的一種變體,二者的差異性,類中成員,如果不宣告,預設是private的,結構體中成員,如果不宣告,則預設是public的。

但是,在c++裡面,二者內部都可以內建成員函式,而c的結構體,內部只允許存在成員變數,如果需要內建成員函式,需要程式設計師顯式宣告函式指標變數,換句話說,就是c在結構體中管理成員函式,是程式設計師自己來管理,c++則是編譯器代為管理。

這意味著什麼呢?

在c++中,成員函式和成員變數,都是類和結構體的成員,但二者有所差異。

編譯器在編譯每個類時,不管這個類以後會例項化幾個物件,首先,它會提取這些類的共性,放到一起,做成乙個表。

比如類裡面的非虛函式,這類函式,所有的物件共享一段函式**,自然沒有必要每個物件內部都設定乙個函式指標,這太浪費記憶體了。

因此,乙個類,所有的非虛函式,會被編譯器排成乙個符號表,放置在特定的編譯期基礎變數區。這實際表現看,是放在exe檔案裡面的,在呼叫乙個程式時,是直接從檔案中讀出,並經過位址修訂,準備使用,這部分連基棧都算不上,算是常量區了,所有的常量也是放在這個區。

嗯,函式內部的靜態變數,類中的靜態變數,靜態函式,都是這個區。

那,除掉這些,類裡面還有什麼呢?

還有虛函式,我們知道,虛函式表示可能繼承,事實上,多次(不是多重)繼承後,乙個類的虛函式內部會有乙個棧,每個虛函式都有乙個棧,每次呼叫該函式,會從棧頂開始call,當然,如果程式設計師願意,也可以在繼承的虛函式內部,通過呼叫父類的同名虛函式,逐級向下call,直至call完所有的虛函式為止。

這就說明,虛函式和普通成員函式不同,每個物件都有可能變化,因此,編譯器就不敢把這個函式的指標,放在常量區,必須跟著物件走,注意,不是類,類是沒有實體的,因此,不存在sizeof,只有物件存在大小。

還有就是普通成員變數,這些內容,每個物件也是不一樣的,因此,每個物件必須自己建立乙個表來管理,否則大家就混了。

因此,我們知道了,每個類,例項化物件之後,其實物件的實體在記憶體中的儲存,就只包含虛函式和普通成員變數,這是c++編譯器為了節約記憶體做得優化。

我們回到你的**看,你的**中,fun2是普通函式,被編譯器放到常量區去了,因此,不占用物件空間,虛函式fun1,則需要占用,我們知道,32位作業系統,乙個指標是4bytes,函式指標也是指標,因此,你的結果是4bytes。

取消了virtual 之後,fun1也變成了普通函式,因此和fun2等同處理,就不再占用物件空間,因此,物件空間為0了。

不過,我隱隱約約聽誰說過,c++語言不允許物件空間為0,這樣的話,物件指標就沒有落點了,因此,乙個物件的空間,至少占用1byte,這就是你的結果為1的原因。

不知道這樣能不能幫你解惑,呵呵,一家之言哈,歡迎拍磚。

c 類物件的記憶體模型

c 類物件記憶體結構 首先介紹一下c 中有繼承關係的類物件記憶體的布局 在c 中,如果類中有虛函式,那麼它就會有乙個虛函式表的指標 vfptr,在類物件最開始的記憶體資料中。之後是類中的成員變數的記憶體資料。對於子類,最開始的記憶體資料記錄著父類物件的拷貝 包括父類虛函式表指標和成員變數 之後是子類...

c 類物件的記憶體模型

c 類物件記憶體結構 首先介紹一下c 中有繼承關係的類物件記憶體的布局 在c 中,如果類中有虛函式,那麼它就會有乙個虛函式表的指標 vfptr,在類物件最開始的記憶體資料中。之後是類中的成員變數的記憶體資料。對於子類,最開始的記憶體資料記錄著父類物件的拷貝 包括父類虛函式表指標和成員變數 之後是子類...

c 類物件的記憶體模型

c 類物件記憶體結構 首先介紹一下c 中有繼承關係的類物件記憶體的布局 在c 中,如果類中有虛函式,那麼它就會有乙個虛函式表的指標 vfptr,在類物件最開始的記憶體資料中。之後是類中的成員變數的記憶體資料。對於子類,最開始的記憶體資料記錄著父類物件的拷貝 包括父類虛函式表指標和成員變數 之後是子類...