分類:
乙個類,有成員變數:靜態與非靜態之分;而成員函式有三種:靜態的、非靜態的、虛的。
那麼這些個東西在記憶體中到底是如何分配的呢?
以乙個例子來說明:
[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...