類中內容在記憶體中到底是如何分配的呢?

2021-08-04 22:43:05 字數 3535 閱讀 7363



分類:

乙個類,有成員變數:靜態與非靜態之分;而成員函式有三種:靜態的、非靜態的、虛的。

那麼這些個東西在記憶體中到底是如何分配的呢?

以乙個例子來說明:

[html]view plaincopyprint?

#include"iostream.h"  

class cobject  

;  void cobject::fun()  

cobject::cobject()  

cobject::~cobject()  

int cobject::a=1;  

void main()  

這是我的一段測試**, 

執行結果是: 

sizeof(cobject):8 

cobject::a=1 

construct! 

sizeof(myobject):8 

sizeof(int)4 

destruct! 

我有疑問如下: 

(1)c++中,應該是物件才會被分配記憶體空間吧??為什麼cobject記憶體大小是8,剛好和兩個

成員變數的大小之和一致!難道還沒例項化的時候,類就 已經有了記憶體空間了? 

(2)當物件生成了之後,算出的記憶體大小怎麼還是8,函式難道不占用記憶體空間嗎?至少應該放個

函式指標在裡面的吧?記憶體是怎樣布局的?

(3)靜態成員應該是屬於類的,怎麼類的大小中沒有包含靜態成員的大小?

下面分別解答如下:

1)sizeof(cobject)是在編譯時就計算了的,乙個類定義了,它所佔的記憶體編譯器就已經知道了,這時只是得到它占用的大小,並沒有分配記憶體操作 。也可以這樣想:編譯器肯定知道大小了,這與分配記憶體空間無關,知道大小了,以後例項化了才能知道要分配多大。

2)類的普通成員、靜態成員函式是不佔類記憶體的,至於你說的函式指標在你的類中有

虛函式的時候存在乙個

虛函式表指標,也就是說如果你的類裡有虛函式則 sizeof(cobject)的值會增加4個位元組。

其實類的成員函式 實際上與 普通的

全域性函式一樣。 

只不過編譯器在編譯的時候,會在成員函式上加乙個引數,傳入這個物件的指標。

成員函式位址是全域性已知的,物件的記憶體空間裡根本無須儲存成員函式位址。 

對成員函式(非虛函式)的呼叫在編譯時就確定了。 

像 myobject.fun() 這樣的呼叫會被編譯成形如 _cobject_fun( &myobject ) 的樣子。

函式是不算到sizeof中的,因為函式是**,被各個物件共用,跟資料處理方式不同。物件中不必有函式指標,因為物件沒必要知道它的各個函式的位址(調 用函式的是其他**而不是該物件)。 

類的屬性是指類的資料成員,他們是例項化乙個物件時就為資料成員分配記憶體了,而且每個物件的資料成員是對立的,而成員函式是共有的~ 

靜態成員函式與一般成員函式的唯一區別就是沒有this指標,因此不能訪問非靜態資料成員。總之,程式中的所有函式都是位於**區的。

3)靜態成員並不屬於某個物件,sizeof取的是物件大小。

知道了上面的時候,就可以改一下來看看:

我也補充一些: 

class cobject 

; 這個類用sizeof()測出來的大小是 2*sizeof(double)=16 

class cobject 

; 大小是2*sizeof(int)=8 

class cobject 

; sizeof(char)+sizeof(int) 先看乙個空的類佔多少空間?

class base

;  class base ;

注意到我這裡顯示宣告了構造跟析構,但是sizeof(base)的結果是1.

因為乙個空類也要例項化,所謂類的例項化就是在記憶體中分配一塊位址,每個例項在記憶體中都有獨一無二的位址。同樣空類也會被例項化,所以編譯器會給空類隱含 的新增乙個位元組,這樣空類例項化之後就有了獨一無二的位址了。所以空類的sizeof為1。

而析構函式,跟建構函式這些成員函式,是跟sizeof無關的,也不難理解因為我們的sizeof是針對例項,而普通成員函式,是針對類體的,乙個類的成 員函式,多個例項也共用相同的函式指標,所以自然不能歸為例項的大小,這在我的另一篇博文有提到。

接著看下面一段**

[html]view plaincopyprint?

class base   

private:   

int  a;                  //佔4位元組   

char *p;                 //4位元組指標   

};   

class derive:public base   

;         

~derive(){};   

private:   

static int st;         //非例項獨佔   

int  d;                     //佔4位元組   

char *p;                    //4位元組指標   

};   

int main()     

class base private: int a; //佔4位元組 char *p; //4位元組指標 }; class derive:public base ; ~derive(){}; private: static int st; //非例項獨佔 int d; //佔4位元組 char *p; //4位元組指標 }; int

main()

結果自然是

base類裡的int  a;char *p;佔8個位元組。

而虛析構函式virtual ~base();的指標佔4子位元組。

其他成員函式不歸入sizeof統計。

derive類首先要具有base類的部分,也就是佔12位元組。

int  d;char *p;佔8位元組

static int st;不歸入sizeof統計

所以一共是20位元組。

在考慮在derive裡加乙個成員char c;

class derive:public base 

; ~derive(){}; 

private: 

static int st; 

int  d; 

char *p; 

char c; 

};  class derive:public base ; ~derive(){}; private:

static int st; int d; char *p; char c; };

這個時候,結果就變成了

乙個char c;增加了4位元組,說明類的大小也遵守類似class位元組對齊,的補齊規則。

具體的可以看我那篇《5分鐘搞定位元組對齊》

至此,我們可以歸納以下幾個原則:

1.類的大小為類的非靜態成員資料的型別大小之和,也 就是說靜態成員資料不作考慮。

2.普通成員函式與sizeof無關。

3.虛函式由於要維護在

虛函式表,所以要佔據乙個指標大小,也就是4位元組。

4.類的總大小也遵守類似class位元組對齊的,調整規則。

2 類在記憶體中是如何分配的

類在記憶體中是如何分配的 乙個類,有成員變數 靜態與非靜態之分 而成員函式有三種 靜態的 非靜態的 虛的。那麼這些個東西在記憶體中到底是如何分配的呢?1 c 中,應該是物件才會被分配記憶體空間吧?為什麼cobject記憶體大小剛好和兩個成員變數的大小之和一致!難道還沒例項化的時候,類就已經有了記憶體...

類在記憶體中的分配

對於乙個宣告好的類,裡面可能有成員函式,靜態成員函式,成員變數,靜態成員變數,虛函式等,那麼這些資料都是怎麼分配到記憶體的呢?class a 乙個簡單的類,方便下面描述資訊 public void show cout i am a 下面給出一些結論以及一些簡單的分析 1.類的普通成員函式以及靜態成員...

類在記憶體中的分配問題

乙個類,有成員變數 靜態與非靜態之分 而成員函式有三種 靜態的 非靜態的 虛的。那麼這些個東西在記憶體中到底是如何分配的呢?以乙個例子來說明 include iostream.h class cobject void cobject fun cobject cobject cobject cobje...