1、c++物件的記憶體分布和虛函式表:
注意,物件中儲存的是虛函式表指標,而不是虛函式表,虛函式表在編譯階段就已經生成,同類的不同物件中的虛函式指標指向同乙個虛函式表,不同類物件的虛函式指標指向不同虛函式表。
2、何時進行動態繫結:
(1)每個類物件在被構造時不用去關心是否有其他類從自己派生,也不需要關心自己是否從其他類派生,只要按照乙個統一的流程:在自身的建構函式執行之前把自己所屬類
(即當前建構函式所屬的類)
的虛函式表的位址繫結到當前物件上(一般是儲存在物件記憶體空間中的前4個位元組)。因為物件的構造是從最基類部分(比如a<-b<-c,a是最基類,c是最派生類)開始構造,一層一層往外構造中間類(b),最後構造的是最派生類(c),所以最終物件上繫結的就自然而然就是最派生類的虛函式表。
(2)
析構函式的呼叫跟建構函式的呼叫順序是相反的,它從最派生類的析構函式開始的。也就是說當基類的析構函式執行時,派生類的析構函式已經執行過,派生類中的成員資料被認為已經無效(包括派生類物件中的虛表指標)。假設基類中虛函式呼叫能呼叫得到派生類的虛函式,那麼派生類的虛函式將訪問一些已經「無效」的資料,所帶來的問題和訪問一些未初始化的資料一樣。而同樣,我們可以認為在析構的過程中,虛函式表也是在不斷變化的,不斷解繫結。
因此,在基類建構函式或者析構函式中呼叫虛函式,並不會繫結到派生類的實現上,因為在這兩個函式執行時虛函式表指標指向的是基類的虛函式表。
3、c++中類的大小:
由 1 可知,c++物件中只儲存非靜態資料成員,成員函式和靜態資料成員是儲存在靜態資料區的。
位元組對齊(預設):
1、vc規定各成員變數存放的起始位址相對於結構的起始位址的偏移量必須為該變數的型別所占用的位元組數的倍數。
2、vc為了確保結構的大小為結構的位元組邊界數(即該結構中占用最大空間的型別所占用的位元組數)的倍數,所以在為最後乙個成員變數申請空間後,還會根據需要自動填充空缺的位元組。
3、如果對齊位元組數(#pragma pack(n)),那麼
(1)各成員變數存放的起始位址相對於結構的起始位址的偏移量必須為
該變數的型別所占用的位元組數和n的
較小值的倍數。
(2)結構的大小為結構中
占用最大空間的型別所占用的位元組數和n的
較小值的
倍數。class a
}; // 8 byte,只有double資料成員佔8位元組,成員函式和靜態資料成員不在物件中,而是在靜態資料區
class b
; // 24 byte,考慮位元組對齊, 4 +
4+ 8 + 1 + 7, 藍色的4是為了滿足條件1,黑色的7是為了滿足條件2。
如果指定4位元組對齊,4 + 8 + 1 + 3
class c
}; // 4 byte,虛函式表指標佔4個位元組
class d
;// 1 byte,沒有成員變數的結構或類的大小為1,因為必須保證結構或類的每一 個例項在記憶體中都有唯一的位址
注:1、如果有成員物件,直接把成員物件展開到外部物件中,然後按照位元組對齊的規律求大小。
2、虛繼承的記憶體分布為:虛類指標-》派生類成員資料-》基類成員資料。其對齊方案是:首先把派生類所有成員當成乙個巢狀結構體形式,位於最下面的基類的資料成員要保證自己對齊(首位址整除自己的位元組數),但是不用在最下面新增位元組保證整體是邊界長度的整數倍(因為基類成員共享,不能把派生類當成乙個整體
)。3、如果物件中有陣列,可以把陣列展開到物件中,然後按照位元組對齊的規律求大小。
4、為什麼要進行位元組對齊
計算機組成原理教導我們這樣有助於加快計算機的取數速度,否則就得多花指令週期了。為此,編譯器缺省會對結構體進行處理(實際上其它地方的資料變數也是如此),讓寬度為
2的基本資料型別(short等)都位於能被2整除的位址上,讓寬度為4的基本資料型別(int等)都位於能被4整除的位址上,以此類推。
比如有些平台每次讀都是從偶位址開始,如果乙個int型(假設為32位系統)如果存放在偶位址開始的地方,那麼乙個讀週期就可以讀出這32bit,而如果存放在奇位址開始的地方,就需要2個讀週期,並對兩次讀出的結果的高低位元組進行拼湊才能得到該32bit資料。
備註:visual studio 2010是按照預設方式進行位元組對齊的
32位gcc按照4位元組最齊
C語言 位元組對齊(記憶體對齊)
1 平台原因 移植原因 不是所有的硬體平台都能訪問任意位址上的任意資料,某些硬體平台只能在某些位址處取某些特定型別的資料,否則丟擲硬體異常 2 硬體原因 經過記憶體對齊之後,cpu的記憶體訪問速度大大提公升。1.對齊原則 原則1 資料成員對齊規則 結構 struct 或聯合 union 的資料成員,...
C 物件的記憶體分布和虛函式表
c 中乙個類中無非有四種成員 靜態資料成員和非靜態資料成員,靜態函式和非靜態函式。1.非靜態資料成員被放在每乙個物件體內作為物件專有的資料成員。2.靜態資料成員被提取出來放在程式的靜態資料區內,為該類所有物件共享,因此只存在乙份。3.靜態和非靜態成員函式最終都被提取出來放在程式的 段中並為該類所有物...
C 物件的記憶體分布和虛函式表
c 中乙個類中無非有四種成員 靜態資料成員和非靜態資料成員,靜態函式和非靜態函式。1.非靜態資料成員被放在每乙個物件體內作為物件專有的資料成員。2.靜態資料成員 被提取出來放在程式的靜態資料區內,為該類所有物件共享 因此只存在乙份。3.靜態和非靜態成員函式 最終都被提取出來放在程式的 段中並為該類所...