淺談C++ 類的實(shí)例中 內(nèi)存分配詳解
一個(gè)類,有成員變量:靜態(tài)與非靜態(tài)之分;而成員函數(shù)有三種:靜態(tài)的、非靜態(tài)的、虛的。
那么這些個(gè)東西在內(nèi)存中到底是如何分配的呢?
以一個(gè)例子來(lái)說(shuō)明:
#include"iostream.h"
class CObject
{
public:
static int a;
CObject();
~CObject();
void Fun();
private:
int m_count;
int m_index;
};
VoidCObject::Fun(){ cout<<"Fun\n"<<endl;}
CObject::CObject(){ cout<<"Construct!\n";}
CObject::~CObject(){ cout<<"Destruct!\n";}
int CObject::a=1;
void main(){
cout<<"Sizeof(CObject):"<<sizeof(CObject)<<endl; cout<<"CObject::a="<<CObject::a<<endl;
CObject myObject;cout<<"sizeof(myObject):"<<sizeof(myObject)<<endl;
cout<<"sizeof(int)"<<sizeof(int)<<endl;
}
這是我的一段測(cè)試代碼, 運(yùn)行結(jié)果是:
Sizeof(CObject):8 CObject::a=1 Construct! sizeof(myObject):8 sizeof(int)4 Destruct!
我有疑問(wèn)如下:
(1)C++中,應(yīng)該是對(duì)象才會(huì)被分配內(nèi)存空間吧??為什么CObject內(nèi)存大小是8,剛好和兩個(gè)成員變量的大小之和一致!難道還沒(méi)實(shí)例化的時(shí)候,類就已經(jīng)有了內(nèi)存空間了?
(2)當(dāng)對(duì)象生成了之后,算出的內(nèi)存大小怎么還是8,函數(shù)難道不占用內(nèi)存空間嗎?至少應(yīng)該放個(gè)函數(shù)指針在里面的吧??jī)?nèi)存是怎樣布局的?
(3)靜態(tài)成員應(yīng)該是屬于類的,怎么類的大小中沒(méi)有包含靜態(tài)成員的大小?
下面分別解答如下:
1)Sizeof(CObject)是在編譯時(shí)就計(jì)算了的,一個(gè)類定義了,它所占的內(nèi)存編譯器就已經(jīng)知道了,這時(shí)只是得到它占用的大小,并沒(méi)有分配內(nèi)存操作 。也可以這樣想:編譯器肯定知道大小了,這與分配內(nèi)存空間無(wú)關(guān),知道大小了,以后實(shí)例化了才能知道要分配多大。
2)類的普通成員、靜態(tài)成員函數(shù)是不占類內(nèi)存的,至于你說(shuō)的函數(shù)指針在你的類中有虛函數(shù)的時(shí)候存在一個(gè)虛函數(shù)表指針,也就是說(shuō)如果你的類里有虛函數(shù)則sizeof(CObject)的值會(huì)增加4個(gè)字節(jié)。
其實(shí)類的成員函數(shù)實(shí)際上與普通的全局函數(shù)一樣。
只不過(guò)編譯器在編譯的時(shí)候,會(huì)在成員函數(shù)上加一個(gè)參數(shù),傳入這個(gè)對(duì)象的指針。
成員函數(shù)地址是全局已知的,對(duì)象的內(nèi)存空間里根本無(wú)須保存成員函數(shù)地址。
對(duì)成員函數(shù)(非虛函數(shù))的調(diào)用在編譯時(shí)就確定了。
像 myObject.Fun() 這樣的調(diào)用會(huì)被編譯成形如 _CObject_Fun( &myObject ) 的樣子。
函數(shù)是不算到sizeof中的,因?yàn)楹瘮?shù)是代碼,被各個(gè)對(duì)象共用,跟數(shù)據(jù)處理方式不同。對(duì)象中不必有函數(shù)指針,因?yàn)閷?duì)象沒(méi)必要知道它的各個(gè)函數(shù)的地址(調(diào)用函數(shù)的是其他代碼而不是該對(duì)象)。
類的屬性是指類的數(shù)據(jù)成員,他們是實(shí)例化一個(gè)對(duì)象時(shí)就為數(shù)據(jù)成員分配內(nèi)存了,而且每個(gè)對(duì)象的數(shù)據(jù)成員是對(duì)立的,而成員函數(shù)是共有的~
靜態(tài)成員函數(shù)與一般成員函數(shù)的唯一區(qū)別就是沒(méi)有this指針,因此不能訪問(wèn)非靜態(tài)數(shù)據(jù)成員??傊?,程序中的所有函數(shù)都是位于代碼區(qū)的。
3)靜態(tài)成員并不屬于某個(gè)對(duì)象,sizeof取的是對(duì)象大小。
知道了上面的時(shí)候,就可以改一下來(lái)看看:
我也補(bǔ)充一些:
class CObject
{
public:
static int a;
CObject();
~CObject();
void Fun();
private:
double m_count; //這里改成了double
int m_index;
};
這個(gè)類用sizeof()測(cè)出來(lái)的大小是 2*sizeof(double)=16
class CObject
{
public:
static int a;
CObject();
~CObject();
void Fun();
private:
char m_count; //這里改成了char
int m_index;
};
大小是2*sizeof(int)=8
class CObject
{
public:
static int a;
CObject();
~CObject();
void Fun();
private:
double m_count; //這里改成了double
int m_index;
char c;
};
sizeof(char)+sizeof(int) <sizeof(double) 所以大小是2*sizeof(double)
其實(shí)這里還有一個(gè)是內(nèi)存對(duì)齊的問(wèn)題。
空類大小是1。
另外要注意的一些問(wèn)題:
先看一個(gè)空的類占多少空間?
class Base
{
public:
Base();
~Base();
};
class Base {
public:
Base();
~Base();
};
注意到我這里顯示聲明了構(gòu)造跟析構(gòu),但是sizeof(Base)的結(jié)果是1.
因?yàn)橐粋€(gè)空類也要實(shí)例化,所謂類的實(shí)例化就是在內(nèi)存中分配一塊地址,每個(gè)實(shí)例在內(nèi)存中都有獨(dú)一無(wú)二的地址。同樣空類也會(huì)被實(shí)例化,所以編譯器會(huì)給空類隱含 的添加一個(gè)字節(jié),這樣空類實(shí)例化之后就有了獨(dú)一無(wú)二的地址了。所以空類的sizeof為1。
而析構(gòu)函數(shù),跟構(gòu)造函數(shù)這些成員函數(shù),是跟sizeof無(wú)關(guān)的,也不難理解因?yàn)槲覀兊膕izeof是針對(duì)實(shí)例,而普通成員函數(shù),是針對(duì)類體的,一個(gè)類的成 員函數(shù),多個(gè)實(shí)例也共用相同的函數(shù)指針,所以自然不能歸為實(shí)例的大小,這在我的另一篇博文有提到。
接著看下面一段代碼
class Base
{
public:
Base();
virtual ~Base(); //每個(gè)實(shí)例都有虛函數(shù)表
void set_num(int num) // 普通成員函數(shù),為各實(shí)例公有,不歸入sizeof統(tǒng)計(jì)
{
a=num;
}
private:
int a; //占4字節(jié)
char *p; //4字節(jié)指針
};
class Derive:public Base
{
public:
Derive():Base(){};
~Derive(){};
private:
static int st; //非實(shí)例獨(dú)占
int d; //占4字節(jié)
char *p; //4字節(jié)指針
};
int main()
{
cout<<sizeof(Base)<<endl;
cout<<sizeof(Derive)<<endl;
return 0;
}
class Base {
public:
Base();
virtual ~Base(); //每個(gè)實(shí)例都有虛函數(shù)表
void set_num(int num) { a=num; } //普通成員函數(shù),為各實(shí)例公有,不歸入sizeof統(tǒng)計(jì)
private:
int a; //占4字節(jié)
char *p; //4字節(jié)指針
};
class Derive:public Base {
public:
Derive():Base(){};
~Derive(){};
private:
static int st; //非實(shí)例獨(dú)占
int d; //占4字節(jié)
char *p; //4字節(jié)指針
};
int main() {
cout<<sizeof(Base)<<endl;
cout<<sizeof(Derive)<<endl;
return 0;
}
結(jié)果自然是
12
20
Base類里的int a;char *p;占8個(gè)字節(jié)。
而虛析構(gòu)函數(shù)virtual ~Base();的指針占4子字節(jié)。
其他成員函數(shù)不歸入sizeof統(tǒng)計(jì)。
Derive類首先要具有Base類的部分,也就是占12字節(jié)。
int d;char *p;占8字節(jié)
static int st;不歸入sizeof統(tǒng)計(jì)
所以一共是20字節(jié)。
在考慮在Derive里加一個(gè)成員char c;
class Derive:public Base
{
public:
Derive():Base(){};
~Derive(){};
private:
static int st;
int d;
char *p;
char c;
};
class Derive:public Base {
public:
Derive():Base(){};
~Derive(){};
private:
static int st;
int d;
char *p;
char c;
};
這個(gè)時(shí)候,結(jié)果就變成了
12
24
一個(gè)char c;增加了4字節(jié),說(shuō)明類的大小也遵守類似class字節(jié)對(duì)齊,補(bǔ)齊規(guī)則。
至此,我們可以歸納以下幾個(gè)原則:
1.類的大小為類的非靜態(tài)成員數(shù)據(jù)的類型大小之和,也就是說(shuō)靜態(tài)成員數(shù)據(jù)不作考慮。
2.普通成員函數(shù)與sizeof無(wú)關(guān)。
以上就是小編為大家?guī)?lái)的淺談C++ 類的實(shí)例中 內(nèi)存分配詳解全部?jī)?nèi)容了,希望大家多多支持我們~
上一篇:淺談#ifndef,#define,#endif的作用和用法
欄 目:C語(yǔ)言
下一篇:淺談c++ vector和map的遍歷和刪除對(duì)象
本文標(biāo)題:淺談C++ 類的實(shí)例中 內(nèi)存分配詳解
本文地址:http://www.jygsgssxh.com/a1/Cyuyan/1885.html
您可能感興趣的文章
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 01-10深入理解C++中常見(jiàn)的關(guān)鍵字含義
- 01-10使用C++實(shí)現(xiàn)全排列算法的方法詳解
- 01-10c++中inline的用法分析
- 01-10深入理解鏈表的各類操作詳解
- 01-10用C++實(shí)現(xiàn)DBSCAN聚類算法
- 01-10全排列算法的非遞歸實(shí)現(xiàn)與遞歸實(shí)現(xiàn)的方法(C++)
- 01-10C++大數(shù)模板(推薦)
- 01-10淺談C/C++中的static與extern關(guān)鍵字的使用詳解
- 01-10深入C/C++浮點(diǎn)數(shù)在內(nèi)存中的存儲(chǔ)方式詳解


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 01-11Mac OSX 打開(kāi)原生自帶讀寫NTFS功能(圖文
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 04-02jquery與jsp,用jquery
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10delphi制作wav文件的方法
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置


