《C++中類對象的內(nèi)存布局和占用空間》 很多C++書籍中都介紹過,一個Class對象需要占用多大的內(nèi)存空間。最權(quán)威的結(jié)論是: *加上編譯器為了CPU計算,作出的數(shù)據(jù)對齊處理。 *加上為了支持虛函數(shù),產(chǎn)生的額外負擔(dān)。 介紹完了理論知識后,再看看再找一個例子看看(注:一下所有結(jié)果都是在VC6.0 開發(fā)環(huán)境中得出的結(jié)論) 一、空類的Size class Car { }; void main() { int size = 0; Car objCar; size = sizeof(objCar); printf("%s %d /r", "Class Car Size:", size); } 輸出結(jié)果:Class Car Size:1 這是為何呢?我想對于這個問題,不僅是剛?cè)胄胁痪玫拈_發(fā)新手,就算有過幾年以上C++開發(fā)經(jīng)驗的開發(fā)人員也未必能說清楚這個。 編譯器在執(zhí)行Car objCar;這行代碼后需要,作出一個Class Car的Object。并且這個Object的地址還是獨一無二的,于是編譯器就會給空類創(chuàng)建一個隱含的一個字節(jié)的空間。 二、只有成員變量的Size class Car { private: int nLength; int nWidth; }; void main() { int size = 0; Car objCar; size = sizeof(objCar); printf("%s %d /r", "Class Car Size:", size); } 輸出結(jié)果:Class Car Size:8 這個結(jié)果很多開發(fā)人員都清楚。在32位系統(tǒng)中,整型變量占4個字節(jié)。這里Class Car中含有兩個整型類型的成員變量,所以Class Size是8。 class Car { private: int nLength; int nWidth; static int sHigh; }; void main() { int size = 0; Car objCar; size = sizeof(objCar); printf("%s %d /r", "Class Car Size:", size); } 輸出結(jié)果:Class Car Size:8 我們這次在Class Car中添加了一個靜態(tài)成員變量,但是Class Size仍然是8個字節(jié)。這正好符合了,結(jié)論中的第一條:非靜態(tài)成員變量總合。 class Car { private: char chLogo int nLength; int nWidth; static int sHigh; }; void main() { int size = 0; Car objCar; size = sizeof(objCar); printf("%s %d /r", "Class Car Size:", size); } 輸出結(jié)果:Class Car Size:12 在類中又插入了一個字符型變量,結(jié)果Class Size變成了12。這個就是編譯器額外添加3個字符變量,做數(shù)據(jù)對齊處理,為了是提高CPU的計算速度。編譯器額外添加的東西我們是無法看見的。這也符合了結(jié)論中的第二條:加上編譯器為了CPU計算,作出的數(shù)據(jù)對齊處理。 既然,我們這樣定義類成員數(shù)據(jù)編譯器會額外的增加空。那么,我們何不在定義類的時候就考慮到數(shù)據(jù)對齊的問題,可以多定義出3個字符類型變量作為預(yù)留變量,既能滿足數(shù)據(jù)對齊的要求,也給自己的程序添加了一些可擴展的空間。 三、只有成員函數(shù)的Size class Car { public: Car(){}; ~Car(){}; public: void Fun(){}; }; void main() { int size = 0; Car objCar; size = sizeof(objCar); printf("%s %d /r", "Class Car Size:", size); } 輸出結(jié)果:Class Car Size:1 噢,這是怎么回事兒呢?再做一個實驗看看。 class Car { public: Car(){}; ~Car(){}; public: void Fun(){}; private: int nLength; int nWidth; }; void main() { int size = 0; Car objCar; size = sizeof(objCar); printf("%s %d /r", "Class Car Size:", size); } 輸出結(jié)果:Class Car Size:8 這次應(yīng)該很清楚的了。函數(shù)是不占用類空間的。第一個例子中的Size為1個字節(jié),正是編譯器為類創(chuàng)建一個隱含的一個字節(jié)的空間 class Car { public: Car(){}; virtual ~Car(){}; public: void Fun(){}; }; void main() { int size = 0; Car objCar; size = sizeof(objCar); printf("%s %d /r", "Class Car Size:", size); } 輸出結(jié)果:Class Car Size:4 這次,讓析構(gòu)函數(shù)為虛函數(shù),看到了Class Size為4。這正是指向Virtual Table的指針vptr的Size。這正好符合了,結(jié)論中的第三條:加上為了支持虛函數(shù),產(chǎn)生的額外負擔(dān)。 到此為止,一個Class Object究竟占用多少內(nèi)存空間,已經(jīng)完全說清楚了。但是,這只是針對單獨類,或者說是基類適用。對于子類,卻不一樣了。有興趣的朋友可以做一些實驗。
《C++ 類里面,函數(shù)占用存儲空間問題 》 先看兩段代碼: 對象的大小是它的數(shù)據(jù)成員所占存儲空間之和,就和結(jié)構(gòu)體一樣。類中的函數(shù)是所有該類對象通用的方法,不算作對象的成員,因此也不算在對象的存儲空間內(nèi) 問題:類里面不管有多少個函數(shù),這個類的對象只占1個字節(jié)的內(nèi)存。這個字節(jié)的內(nèi)存的內(nèi)容是什么?是指針嗎?指針不是占4個字節(jié)嗎? 當類中類有定義任何變量的時候,類的對象都是1個字節(jié)的,當類中沒有任何變量的時候,這個類里沒有任何真正的成員變量,所以大小應(yīng)該是0,但0大小不好在內(nèi)存中定位一個地址,所以,就規(guī)定它大小為0的對象要占一字節(jié)空間,以便讓它擁有一個合法的地址。如果是有派生類的,還有考慮到內(nèi)存對齊的問題的。
另外涉及到虛函數(shù)的話又不一樣了。如 class A 原因是涉及到虛函數(shù)的實現(xiàn)問題。 class Class1 { m_data1; m_data2; virtual vfunc1() virtual vfunc2() virtual vfunc3() };
所以回到原來的問題,A中只有一個或者幾個虛函數(shù)的話,沒有成員變量,那么類A相當于含有一個vptr指向虛函數(shù)表的指針,所以sizeof(A)=4。 還有一點,如 class B { }; class B2 { }; class C:public B { }; class D:public virtual B { }; class E:public B,public B2 { }; sizeof(B) = 1; sizeof(B2) = 1; sizeof(C) = 1; sizeof(D) = 4; sizeof(E) = 1; 空類所占空間為一(上文以解釋),單一繼承的空類空間也是1,多重繼承的空類空間還是1,但是虛繼承涉及到虛表(虛指針),所以sizeof(D)=4。 |
|