[C++对象模型][6]sizeof与对象内存布局
有了前面幾節(jié)的鋪墊,本節(jié)開始摸索C++的對(duì)象的內(nèi)存布局,平臺(tái)為windows32位+VS2008。
一 內(nèi)置類型的size
內(nèi)置類型,直接上代碼,幫助大家加深記憶:
Codevoid TestBasicSizeOf()
{
??? cout << __FUNCTION__ << endl;
??? cout <<?"? sizeof(char)= "?<<?sizeof ( char ) << endl;
??? cout <<?"? sizeof(int)= "?<<?sizeof ( int ) << endl;
??? cout <<?"? sizeof(float)= "?<<?sizeof ( float ) << endl;
??? cout <<?"? sizeof(double)= "?<<?sizeof ( double ) << endl;
??? cout <<?"? sizeof('$')="?<<?sizeof ( '$' ) << endl;
??? cout <<?"? sizeof(1)= "?<<?sizeof ( 1 ) << endl;
??? cout <<?"? sizeof(1.5f)= "?<<?sizeof ( 1.5f ) << endl;
??? cout <<?"? sizeof(1.5)= "?<<?sizeof ( 1.5 ) << endl;
??? cout <<?"? sizeof(Good!)= "?<<?sizeof ( "Good!" ) << endl ;
??? char? str[] =?"CharArray!";
??? int? a[10];?
??? double? xy[10];
??? cout <<?"? char str[] = \"CharArray!\","?<<?" sizeof(str)= "?<<?sizeof (str) << endl;
??? cout <<?"? int a[10],"?<<?" sizeof(a)= "?<<?sizeof (a) << endl;
??? cout <<?"? double xy[10],"?<<?" sizeof(xy)= "?<<?? sizeof (xy) << endl;
??? cout <<?"? sizeof(void*)= "?<<?sizeof(void*) << endl;
}
運(yùn)行結(jié)果如下:
二 struct/class的大小
在C++中我們知道struct和class的唯一區(qū)別就是默認(rèn)的訪問級(jí)別不同,struct默認(rèn)為public,而class的默認(rèn)為private。所以考慮對(duì)象的大小,我們均以struct為例。對(duì)于struct的大小對(duì)于初學(xué)者來說還確實(shí)是個(gè)難回答的問題,我們就通過下面的一個(gè)struct定義加逐步的變化來引出相關(guān)的知識(shí)。
代碼如下:
Codestruct?st1
{
????short?number;
????float?math_grade;
????float?Chinese_grade;
????float?sum_grade;
????char??level;
}; //20
struct?st2
{
????char??level;
????short?number;
????float?math_grade;
????float?Chinese_grade;
????float?sum_grade;
};//16
#pragma?pack(1)
struct?st3
{
????char??level;
????short?number;
????float?math_grade;
????float?Chinese_grade;
????float?sum_grade;
}; //15
#pragma?pack()?
void?TestStructSizeOf()
{
????cout?<<?__FUNCTION__?<<?endl;
????cout?<<?"??sizeof(st1)=?"?<<?sizeof?(st1)?<<?endl;
????cout?<<?"??offsetof(st1,number)?"?<<?offsetof(st1,number)?<<?endl;
????cout?<<?"??offsetof(st1,math_grade)?"?<<?offsetof(st1,math_grade)?<<?endl;
????cout?<<?"??offsetof(st1,Chinese_grade)?"?<<?offsetof(st1,Chinese_grade)?<<?endl;
????cout?<<?"??offsetof(st1,sum_grade)?"?<<?offsetof(st1,sum_grade)?<<?endl;
????cout?<<?"??offsetof(st1,level)?"?<<?offsetof(st1,level)?<<?endl;
????cout?<<?"??sizeof(st2)=?"?<<?sizeof?(st2)?<<?endl;
????cout?<<?"??offsetof(st2,level)?"?<<?offsetof(st2,level)?<<?endl;
????cout?<<?"??offsetof(st2,number)?"?<<?offsetof(st2,number)?<<?endl;
????cout?<<?"??offsetof(st2,math_grade)?"?<<?offsetof(st2,math_grade)?<<?endl;
????cout?<<?"??offsetof(st2,Chinese_grade)?"?<<?offsetof(st2,Chinese_grade)?<<?endl;
????cout?<<?"??offsetof(st2,sum_grade)?"?<<?offsetof(st2,sum_grade)?<<?endl;
????cout?<<?"??sizeof(st3)=?"?<<?sizeof?(st3)?<<?endl;
????cout?<<?"??offsetof(st3,level)?"?<<?offsetof(st3,level)?<<?endl;
????cout?<<?"??offsetof(st3,number)?"?<<?offsetof(st3,number)?<<?endl;
????cout?<<?"??offsetof(st3,math_grade)?"?<<?offsetof(st3,math_grade)?<<?endl;
????cout?<<?"??offsetof(st3,Chinese_grade)?"?<<?offsetof(st3,Chinese_grade)?<<?endl;
????cout?<<?"??offsetof(st3,sum_grade)?"?<<?offsetof(st3,sum_grade)?<<?endl;
}
?
運(yùn)行結(jié)果如下;
基于上面的對(duì)struct的測試,我們是不是有些驚呆哦,對(duì)于C++的初學(xué)者更是情不自禁的說:“我靠!原來順序不同所占空間都不同啊,還有那個(gè)pack是啥東東啊?”,其實(shí)這里蘊(yùn)含了一個(gè)內(nèi)存對(duì)齊的問題,在計(jì)算機(jī)的底層進(jìn)行內(nèi)存的讀寫的時(shí)候,如果內(nèi)存對(duì)齊的話可以提高讀寫效率,下面是VC的默認(rèn)規(guī)則:
1) 結(jié)構(gòu)體變量的首地址能夠被其最寬基本類型成員的大小所整除;
2) 結(jié)構(gòu)體每個(gè)成員相對(duì)于結(jié)構(gòu)體首地址的偏移量(offset)都是成員大小的整數(shù)倍, 如有需要編譯器會(huì)在成員之間加上填充字節(jié)(internal adding);
3) 結(jié)構(gòu)體的總大小為結(jié)構(gòu)體最寬基本類型成員大小的整數(shù)倍,如有需要編譯器會(huì)在最末一個(gè)成員之后加上填充字節(jié)(trailing padding)。
當(dāng)然VC提供了工程選項(xiàng)/Zp[1|2|4|8|16]可以修改對(duì)齊方式,當(dāng)然我們也可以在代碼中對(duì)部分類型實(shí)行特殊的內(nèi)存對(duì)齊方式,修改方式為#pragma pack( n ),n為字節(jié)對(duì)齊
數(shù),其取值為1、2、4、8、16,默認(rèn)是8,取消修改用#pragma pack(),如果結(jié)構(gòu)體某成員的sizeof大于你設(shè)置的,則按你的設(shè)置來對(duì)齊。
三 struct的嵌套
1)實(shí)例:
Codestruct?A
{
????int?i;
????char?c;
????double?d;
????short?s;
};?//?24
struct?B
{
????char?cc;
????A?a;
????int?ii;
};?//?40
?
布局:(使用VS的未發(fā)布的編譯選項(xiàng)/d1 reportAllClassLayout 或 /d1 reportSingleClassLayout)
?
2)實(shí)例:
Code#pragma?pack(4)
struct?A2
{
????int?i;
????char?c;
????double?d;
????short?s;
};?//?20
#pragma?pack()
struct?B2
{
????char?cc;
????A2?a;
????int?ii;
};?//?28
?
布局:(使用VS的未發(fā)布的編譯選項(xiàng)/d1 reportAllClassLayout 或 /d1 reportSingleClassLayout)
總結(jié):
由于結(jié)構(gòu)體的成員可以是復(fù)合類型,比如另外一個(gè)結(jié)構(gòu)體,所以在尋找最寬基本類型成員時(shí),應(yīng)當(dāng)包括復(fù)合類型成員的子成員,而不是把復(fù)合成員看成是一個(gè)整體。但在確定復(fù)合類型成員的偏移位置時(shí)則是將復(fù)合類型作為整體看待。
四 空struct/class和const,static成員
實(shí)例:
Codestruct?empty{};?//?1
struct?constAndStatic
{
????const?int?i;
????static?char?c;
????const?double?d;
????static?void?TestStatic(){}
????void?TestNoStatic(){}
};?//?16
?
布局:(使用VS的未發(fā)布的編譯選項(xiàng)/d1 reportAllClassLayout 或 /d1 reportSingleClassLayout)
上面的實(shí)例中empty的大小為1,而constAndStatic的大小為16。
總結(jié):
因?yàn)閟tatic成員和函數(shù)其實(shí)是類層次的,不在對(duì)象中分配空間,而成員函數(shù)其實(shí)是被編譯為全局函數(shù)了,所以也不在對(duì)象中。
五 本節(jié)完,下次探討虛函數(shù)對(duì)內(nèi)存布局的影響!
轉(zhuǎn)載于:https://www.cnblogs.com/itech/archive/2009/02/25/1396740.html
總結(jié)
以上是生活随笔為你收集整理的[C++对象模型][6]sizeof与对象内存布局的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 天炎菲尔和天道无极哪个比较好
- 下一篇: [导入]Learning.ASP.NET