sizeof计算类的大小
1 sizeof一個(gè)空類
class A { };cout<<sizeof(A)<<endl;//1注:class A是一個(gè)空類型,它的實(shí)例不包含任何信息,本來(lái)求sizeof應(yīng)該是0。
但當(dāng)我們聲明該類型的實(shí)例的時(shí)候,它必須在內(nèi)存中占有一定的空間,否則無(wú)法使用這些實(shí)例。
至于占用多少內(nèi)存,由編譯器決定。Visual Studio 2008中每個(gè)空類型的實(shí)例占用一個(gè)byte的空間。
?
2 sizeof一個(gè)帶有構(gòu)造和析構(gòu)函數(shù)的類
class B{public:B() {}~B() {}};cout<<szieof(B)<<endl;//1
注:class B在class A的基礎(chǔ)上添加了構(gòu)造函數(shù)和析構(gòu)函數(shù)。
? ? ? ?由于構(gòu)造函數(shù)和析構(gòu)函數(shù)的調(diào)用與類型的實(shí)例無(wú)關(guān)(調(diào)用它們只需要知道函數(shù)地址即可),在它的實(shí)例中不需要增加任何信息。
? ? ? ?所以sizeof(B)和sizeof(A)一樣,在Visual Studio 2008中都是1。
?
3 sizeof一個(gè)帶有虛函數(shù)的類
class C{public:C() {}virtual ~C() {}};cout<<sizeof(C)<<endl;//4
注:class C在class B的基礎(chǔ)上把析構(gòu)函數(shù)標(biāo)注為虛擬函數(shù)。C++的編譯器一旦發(fā)現(xiàn)一個(gè)類型中有虛擬函數(shù),
? ? ? ?就會(huì)為該類型生成虛函數(shù)表,并在該類型的每一個(gè)實(shí)例中添加一個(gè)指向虛函數(shù)表的指針。
? ? ? ?在32位的機(jī)器上,一個(gè)指針占4個(gè)字節(jié)的空間,因此sizeof(C)是4。
? ? ? ?C++標(biāo)準(zhǔn)規(guī)定類的大小不為0,空類的大小為1,當(dāng)類不包含虛函數(shù)和非靜態(tài)數(shù)據(jù)成員時(shí),其對(duì)象大小也為1。
? ? ? ?如果在類中聲明了虛函數(shù)(不管是1個(gè)還是多個(gè)),那么在實(shí)例化對(duì)象時(shí),編譯器會(huì)自動(dòng)在對(duì)象里安插一個(gè)指針指向虛函數(shù)表VTable,
? ? ? ?在32位機(jī)器上,一個(gè)對(duì)象會(huì)增加4個(gè)字節(jié)來(lái)存儲(chǔ)此指針,它是實(shí)現(xiàn)面向?qū)ο笾卸鄳B(tài)的關(guān)鍵。而虛函數(shù)本身和其他成員函數(shù)一樣,是不占用對(duì)象的空間的。
?
4 sizeof一個(gè)帶有成員變量的類
class D {char ch;void func() { }};class E {char ch1; //占用1字節(jié)char ch2; //占用1字節(jié)virtual void func() { }}; class F {int in;virtual void func() { }};cout << "D的大小"<< sizeof(D) << endl;//1 cout << "E的大小" << sizeof(E) << endl;//8 cout << "F的大小" << sizeof(E) << endl;//8注:類和結(jié)構(gòu)體一樣,需要考慮數(shù)據(jù)對(duì)齊和補(bǔ)齊規(guī)則
5 sizeof簡(jiǎn)單繼承類
class COneMember{public:COneMember(int iValue = 0){m_iOne = iValue;};private:int m_iOne;};內(nèi)存結(jié)構(gòu):00 00 00 00 //m_iOneclass CTwoMember:public COneMember{private:int m_iTwo;};內(nèi)存結(jié)構(gòu):00 00 00 00 //m_iOneCC CC CC CC //m_iTwo注:子類成員接在父類成員之后class CThreemember:public CTwoMember{public:CThreemember(int iValue=10) {m_iThree = iValue;};private:int m_iThree;}; 內(nèi)存結(jié)構(gòu): 00 00 00 00 //m_iOneCC CC CC CC //m_iTwo0A 00 00 00 //m_iThree注:孫類成員接在子類之后,再再繼承就依此類推了。cout<<sizeof(COneMember)<<endl;//4 cout<<sizeof(CTwoMember)<<endl;//8 cout<<sizeof(CThreeeMember)<<endl;//12
6 sizeof多重繼承類
class ClassA{public:ClassA(int iValue=1){m_iA = iValue;};private:int m_iA;};class ClassB{public:ClassB(int iValue=2){m_iB = iValue;};private:int m_iB;};class ClassC{public:ClassC(int iValue=3){m_iC = iValue;};private:int m_iC;};class CComplex :public ClassA, public ClassB, public ClassC{public:CComplex(int iValue=4){m_iComplex = iValue;};private:int m_iComplex;};內(nèi)存結(jié)構(gòu): 01 00 00 00 //A02 00 00 00 //B03 00 00 00 //C04 00 00 00 //Complex注:也是父類成員先出現(xiàn)在前邊,我想這都足夠好理解。cout<<sizeof(CComplex )<<endl;//16
7 sizeof 虛繼承的類
class CTwoMember:virtual public COneMember{private:int m_iTwo;};內(nèi)存結(jié)構(gòu):E8 2F 42 00 //指針,指向一個(gè)關(guān)于偏移量的數(shù)組,且稱之虛基類偏移量表指針CC CC CC CC // m_iTwo00 00 00 00 // m_iOne(虛基類數(shù)據(jù)成員)長(zhǎng)度:12注:virtual讓長(zhǎng)度增加了4,其實(shí)是多了一個(gè)指針。
8 sizeof一個(gè)閉合虛繼承類
內(nèi)存結(jié)構(gòu):
14 30 42 00 //ClassB的虛基類偏移量表指針
02 00 00 00 //m_iB
C4 2F 42 00 //ClassC的虛基類偏移量表指針
03 00 00 00 //m_iC
04 00 00 00 //m_iComplex
01 00 00 00 //m_iA
長(zhǎng)度:24
注:虛基類的成員m_iA只出現(xiàn)了一次,而且是在最后邊。虛繼承利用一個(gè)“虛基類偏移量表指針”來(lái)使得虛基類即使被重復(fù)繼承也只會(huì)出現(xiàn)一次。
?
9 sizeof一個(gè)帶有static數(shù)據(jù)成員的類
class CStaticNull{public:CStaticNull(){printf("Construct/n");}~CStaticNull(){printf("Desctruct/n");}static void Foo(){printf("Foo/n");}static int m_iValue;};內(nèi)存結(jié)構(gòu):和空類相同 長(zhǎng)度:1 注:static成員不會(huì)占用類的大小,static成員的存在區(qū)域?yàn)殪o態(tài)區(qū),可認(rèn)為它們是“全局”的,只是不提供全局的訪問(wèn)而已,這跟C的static其實(shí)沒(méi)什么區(qū)別。
10 帶有一個(gè)虛函數(shù)的空類
class CVirtualNull{public:CVirtualNull(){printf("Construct/n");}~CVirtualNull(){printf("Desctruct/n");}virtual void Foo(){printf("Foo/n");}};內(nèi)存結(jié)構(gòu): 00 31 42 00 //指向虛函數(shù)表的指針(虛函數(shù)表后面簡(jiǎn)稱“虛表”)00423100:(虛表) 41 10 40 00 //指向虛函數(shù)Foo的指針00401041: E9 78 02 00 00 E9 C3 03 … //函數(shù)Foo的內(nèi)容(看不懂)長(zhǎng)度:4 注:虛函數(shù)的類長(zhǎng)度就增加了4,這個(gè)4其實(shí)就是個(gè)指針,指向虛函數(shù)表的指針,上面這個(gè)例子中虛表只有一個(gè)函數(shù)指針,值就是“0x00401041”,指向的這個(gè)地址就是函數(shù)的入口了
11 sizeof一個(gè)繼承帶虛函數(shù)的類
class CVirtualDerived : public CVirtualNull{public:CVirtualDerived(){m_iVD=0xFF;};~CVirtualDerived(){};private:int m_iVD;};長(zhǎng)度:8 內(nèi)存結(jié)構(gòu): 3C 50 42 00 //虛表指針 FF 00 00 00 //m_iVD0042503C:(虛表) 23 10 40 00 //指向虛函數(shù)Foo的指針,如果這時(shí)候創(chuàng)建一個(gè)CVirtualNull對(duì)象,會(huì)發(fā)現(xiàn)它的 虛表的內(nèi)容跟這個(gè)一樣注:由于父類帶了虛函數(shù),子類就算沒(méi)有顯式聲明虛函數(shù),虛表還是存在的,虛表存放的位置跟父類不同,但內(nèi)容是同的,也就是對(duì)父類虛表的復(fù)制。
12 sizeof子類帶虛函數(shù),基類帶虛函數(shù)
class CVirtualDerived: public CVirtualNull{public:CVirtualDerived(){m_iVD=0xFF;};~CVirtualDerived(){};virtual void Foo2(){printf("Foo2/n");};private:int m_iVD;};內(nèi)存結(jié)構(gòu): 24 61 42 00 //虛表指針 FF 00 00 00 //m_iVD00426124:(虛表) 23 10 40 00 50 10 40 00長(zhǎng)度:8 注:虛表還是只有一張,不會(huì)因?yàn)樵黾恿诵碌奶摵瘮?shù)而多出另一張來(lái),新的虛函數(shù)的指針將添加在復(fù)制了的虛表的后面。
轉(zhuǎn)載于:https://www.cnblogs.com/LuckCoder/p/10452766.html
總結(jié)
以上是生活随笔為你收集整理的sizeof计算类的大小的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 用互斥锁实现程序只能有一个实例
- 下一篇: 看完源码记不住,是我记性太差了吗?