C 物件模型

2021-10-07 15:25:30 字數 2713 閱讀 8194

1 2

33.1 data member繫結

編譯器以對類宣告中函式內出現的變數的決議在類宣告結束後進行,而類內函式引數列表則在第一次出現時被決議,所以請把nested type宣告放在類宣告起始處。

3.2 data member布局

c++規範要求各access section內變數在記憶體中與宣告順序一致,而各access section順序未限制,當前都是將access sections連在一起

3.3 data member訪問

當使用指標訪問成員時,若在其繼承結構中有乙個virtual base class,且訪問的是該virtual base class時,會和使用類物件直接訪問有重大差別。由於無法在編譯時確定指標具體指向何種型別,無法確定變數offset,需要在執行期先從物件中獲取virtual base class的位址,然後找到成員。

3.4 繼承

當虛繼承出現時,class將被分割為 不變區域性 和 共享區域性 兩部分。一般先安排不變區域性,然後再安排共享區域性。

主要有三種實現策略:

cfront原始模型 於每個derived class object內安插指標,指向virtual base class. 但有兩個缺點  a虛基類越多插入指標越多,空間負載變大  b繼承串鏈增長時間接訪問次數會不斷增加

由鑑於此: 1). 一些編譯器拷貝nested virtual base class指標,以空間換時間

2). ms作法,加入virtual base class table,每個物件內插入vbptr指標

3). 在vftbl中放置 virtual base class 的offset

3.5 物件成員的效率

3.6 指向資料成員指標

int myclass::*p = &myclass::m_x;     p返回值在不同編譯器有不同情況,一般為1, 5, 9..etc 1, 5, 9 的情況可以區分出「沒有指向任何member成員的指標(0)」和「指向第乙個member成員的指標(1)」,實際使用指標時應將p-1    ;vc中為0, 4, 8..etc  對於"沒有指向任何member成員的指標"vc把它賦值為0xffffffff以此區分前述情況. 4

4.1 member的各種呼叫方式

1) nonstatic member functions               

與 nonmember function有相同效率,使用name mangling等手段轉換為接受this指標為引數的函式

2) virtual member functions

ptr->myfun(); 會轉換為 (*ptr->vptr[x])(ptr);

3) static member function

沒有this指標與nonmember function有相同

4.2 virtual member functions

class object上需要有class型別資訊(字串或數字)和vptr以及額外的虛函式表 ptr->myfun(); 會轉換為 (*ptr->vptr[x])(ptr);

多重繼承時第乙個base class直接可以使用指向物件開始處的this,其第二個及後繼base class需要調整this指標來支援虛函式,有三種情況:a)通過pbase2 呼叫子類函式delete pbase2;(要呼叫derived::~derived)   b)通過pderived呼叫base2的虛函式 pderived->base2virtualfunc(); c)虛函式返回值有變化derived* derived::clone(); pbase1 = new derived; pbase2 = pbase1->clone();  調整this指標的有種trunk技術,編譯器內部各自使用了不同方法來解決調整this指標的問題

虛繼承,盡量不要在虛基類中宣告nonstatic data members。

4.3 函式效能

4.4 指向成員函式的指標

取nonstatic nonvirtual成員函式之位址,得到是記憶體位址,型別double (myclass::*pmf)(),取static成員函式之位址得到記憶體位址,型別double (*pmf)();取virtual成員函式位址得到vtbl中的順序號。

使用指向成員函式的指標時在沒有virtual函式,多重繼承,虛基類的情況下和普通函式指標有同樣的效率。

pmf可能是記憶體位址也可能是vtbl順序號,為此開始cfront使用了如下手段支援virtual函式

(  (int)pmf & ~127)  ?  (*pmf)(ptr)  : (* ptr->vtble[(int)pmf]) (ptr);//最多128個虛函式

多重繼承下使用了乙個結構體來實現 

struct __mptr ;

}; 

指向成員函式指標的效能

4.5 inline functions

編譯器會根據自己的機制來決定定函式是否可以成為inline functions。

inline函式會在被呼叫的那一點上擴充套件,它會涉及到引數求值和臨時物件的管理。

1)形參    若是常量表示式則直接繫結到引數上,若是有***的表示式,則需要引入臨時物件以避免重複求值。

inline min(int i , int j){return i x= ( t1= foo(),t2=foo2(),t1 2)區域性變數

若inline中若有區域性變數,多次擴充套件後要維護的區域性變數會很多。

使用inline函式時,若呼叫次數太多,會使程式體積變大,但它可以有效訪問nonpublic資料,相比巨集對類封裝性提供了較好支援。

c 物件模型

很久之前就想總結一下c 的記憶體使用機制。直到現在剛考完試之制,去實習之前,才有時間完成這事。1.程式使用記憶體區 乙個程式占用的記憶體區一般分為5種 1 全域性 靜態資料區 儲存全域性變數及靜態變數 包括全域性靜態變數和區域性靜態變數 2 常量資料區 儲存程式中的常量字串等。3 區 儲存程式的 4...

C 物件模型

很久之前就想總結一下c 的記憶體使用機制。直到現在剛考完試之制,去實習之前,才有時間完成這事。1.程式使用記憶體區 乙個程式占用的記憶體區一般分為5種 1 全域性 靜態資料區 儲存全域性變數及靜態變數 包括全域性靜態變數和區域性靜態變數 2 常量資料區 儲存程式中的常量字串等。3 區 儲存程式的 4...

C 物件模型

簡單物件模型 乙個c 物件儲存了所有指向成員的指標,而成員本身不儲存在物件中。也就是說不論資料成員還是成員函式,也不論這個是普通成員函式還是虛函式,它們都儲存在物件本身之外,同時物件儲存指向它們的指標。示意圖如右。簡單物件模型對於編譯器來說雖然極盡簡單,但同時付出的代價是空間和執行期的效率.顯而易見...