類在記憶體中的分配問題

2021-06-10 14:48:50 字數 3186 閱讀 4716

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

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

以乙個例子來說明:

#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指標,因此不能訪問非靜態資料成員。this指標其實就是物件的首位址,儲存在暫存器中。總之,程式中的所有函式都是位於**區的。

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

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

我也補充一些: 

class cobject 

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

class cobject 

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

class cobject 

; sizeof(char)+sizeof(int)

其實這裡還有乙個是記憶體對齊的問題。

空類大小是1。 

另外要注意的一些問題:

先看乙個空的類佔多少空間?

class base  

;  

class base ;

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

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

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

接著看下面一段**

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() ;  

~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; };

這個時候,結果就變成了

1224

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

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

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

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

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

3.虛函式由於要維護在虛函式表,所以要佔據乙個指標大小,也就是4位元組。

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

類在記憶體中的分配

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

C 類在記憶體中的分配

在網上看到這樣一道題 答案是24位元組。做這道題要理解三個知識點 一 32位和64位作業系統的區別 32位和64位指的是cpu一次處理資料的能力是32位還是64位,這裡涉及到的是處理器運算位數。簡單的說32位系統的位址匯流排是32位的,而64位系統的位址匯流排是64位的,這意味著乙個指標所占用的空間...

c 類例項在記憶體中的分配

c 是一種物件導向的程式語言,它向下保持了對c的相容,同時也允許程式設計師能夠自由的操控記憶體,雖然會帶來一些問題,但這不是我們要 的問題,略過不表。類是對某種物件的定義,包含變數和方法,也可以理解為現實生活中一類具有共同特徵的事務的抽象,他是物件導向語言的基礎。所以類是不占有記憶體的,可是如果類生...