日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

[C++对象模型][6]sizeof与对象内存布局

發(fā)布時(shí)間:2023/11/27 生活经验 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [C++对象模型][6]sizeof与对象内存布局 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

有了前面幾節(jié)的鋪墊,本節(jié)開始摸索C++的對(duì)象的內(nèi)存布局,平臺(tái)為windows32位+VS2008。

一 內(nèi)置類型的size

內(nèi)置類型,直接上代碼,幫助大家加深記憶:

Code
void 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í)。

代碼如下:

Code
struct?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í)例:

Code
struct?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í)例:

Code
struct?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)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。