c++將nonstatic data members直接放在每乙個class object中。對於繼承而來的nonstatic data members(不管是virtual或是nonvirtual base class)也是如此.static data members被放置在程式的乙個global data segment中,不會影響個別的class object的大小。在程式中,不管class被產生出多少個objects,static data members永遠只有1份實體(甚至,即時該class沒有object實體,其static data member也已經存在)。
point3d origin;
point3d &p;
origin.x = 0.0;
p->x = 0.0;
//問題:通過origin和p訪問x,開銷有什麼區別?從class和data member的角度來分析。
首先,要區分x是static還是nonstatic。如果是static,那麼不管是origin還是p,他們是沒有任何區別的。因為static data member是放在data segment中,不同class的如果有名稱衝突,就用name mangling來解決。
其次,如果x是nonstatic data member。在編譯時期,會把nonstatic data member直接複製到子類中,所以他的偏移量是已經確定了的。不管是class本身就有的,還是繼承來的(包括多重繼承)。但是,如果data member是從virtual base class繼承來的,那麼就會慢一些,因為通過指標我們無法確定p到底指向的是誰,所以要到執行期才能確定。而point3d origin,就一定是乙個point3d所以data member的偏移量在編譯時就確定了。
為了支援多型,增加了virtual function,必然帶來空間和訪問時間的額外負擔,主要表現如下: 多重繼承,按照宣告的順序,從上到下依次排列 subobject。所以,無論是訪問哪乙個的data member,都不需要付出額外的成本。members的位置在編譯的時候就固定了,因此訪問members只是乙個簡單的offset運算,就像單一繼承一樣簡單—-不管是經由乙個指標、乙個reference或是乙個object來訪問。
總體思路就是把資料分為固定部分和共享部分。固定部分直接放到前面,不在變化。共享部分就是virtual base class的部分,有兩種處理辦法,分別對應兩種記憶體布局。
區分為了區分乙個沒有指向任何data member的指標,和乙個指向第乙個data member的指標,所以每乙個真正的member offset值都被加上一。& point3d::x 和 & origin.x
:取乙個nonstatic data member的位址,將會得到它在class中的offset。
&point3d::x
繫結於真正class object身上的data member的位址,將會得到該member在記憶體中的真正位址。& origin.x
float point3d::*p1 = 0;
float point3d::*p2 = &point3d::x;
if ( p1 == p2)
// 這個是可以區分的,因為就算x在第乙個,他的offset也被加了1. 也就是說 &point3d::x表示取x的offset,而offset都是真實的offset+1。
深度探索C 物件模型之C 物件模型筆記
0.菜鳥覺得,在看這本書的時候最好切換角色,把自己的思維轉換成編譯器開發者,去考慮問題,這樣會容易理解些.當然這樣很難,就想著自己要解決什麼樣的問題好了 1.在c 中,類的資料成員有兩種 靜態和非靜態 成員函式有三種 靜態,非靜態 虛函式。之所以這樣分,大概是因為在設計c 物件模型時,非靜態的資料成...
C 之物件模型二
c 程式設計之記憶體模型 c 程式在執行時,將記憶體大方向劃分為四個區域 區 存放函式體的二進位制 由作業系統進行管理的 全域性區 存放全域性變數 靜態變數和常量 棧區 由編譯器自動分配釋放,存放函式的引數值 區域性變數等 堆區 由程式設計師分配和釋放,若程式設計師不釋放,程式結束時由作業系統收回 ...
深入探索C 物件模型之物件
物件 一 在c語言中,資料 和 對資料的處理 函式 分開宣告的,也就是說,語言本身並沒有支援 資料和函式 之間的關聯性。例如,typedef struct point3dpoint3d 而在c 中,座標型別和座標數目都可以引數化 template class point type operator ...