C++中類對象的內存佈局和佔用空間

很多C++書籍中都介紹過,一個Class對象需要佔用多大的內存空間。最權威的結論是:
*非靜態成員變量總合。
*加上編譯器爲了CPU計算,作出的數據對齊處理。
*加上爲了支持虛函數,產生的額外負擔。
介紹完了理論知識後,再看看再找一個例子看看(注:一下所有結果都是在VC6.0 開發環境中得出的結論)
一、空類的Size
class Car
{
};
void main()
{
       int size = 0;
       Car objCar;
       size = sizeof(objCar);
printf("%s %d /r", "Class Car Size:", size);
}
輸出結果:Class Car Size:1
這是爲何呢?我想對於這個問題,不僅是剛入行不久的開發新手,就算有過幾年以上C++開發經驗的開發人員也未必能說清楚這個。
編譯器在執行Car objCar;這行代碼後需要,作出一個Class Car的Object。並且這個Object的地址還是獨一無二的,於是編譯器就會給空類創建一個隱含的一個字節的空間。
二、只有成員變量的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);
}
輸出結果:Class Car Size:8
這個結果很多開發人員都清楚。在32位系統中,整型變量佔4個字節。這裏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);
}
輸出結果:Class Car Size:8
我們這次在Class Car中添加了一個靜態成員變量,但是Class Size仍然是8個字節。這正好符合了,結論中的第一條:非靜態成員變量總合。
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);
}
輸出結果:Class Car Size:12
在類中又插入了一個字符型變量,結果Class Size變成了12。這個就是編譯器額外添加3個字符變量,做數據對齊處理,爲了是提高CPU的計算速度。編譯器額外添加的東西我們是無法看見的。這也符合了結論中的第二條:加上編譯器爲了CPU計算,作出的數據對齊處理。
既然,我們這樣定義類成員數據編譯器會額外的增加空。那麼,我們何不在定義類的時候就考慮到數據對齊的問題,可以多定義出3個字符類型變量作爲預留變量,既能滿足數據對齊的要求,也給自己的程序添加了一些可擴展的空間。
三、只有成員函數的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);
}
輸出結果: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);
}
輸出結果:Class Car Size:8
這次應該很清楚的了。函數是不佔用類空間的。第一個例子中的Size爲1個字節,正是編譯器爲類創建一個隱含的一個字節的空間
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);
}
輸出結果:Class Car Size:4
這次,讓析構函數爲虛函數,看到了Class Size爲4。這正是指向Virtual Table的指針vptr的Size。這正好符合了,結論中的第三條:加上爲了支持虛函數,產生的額外負擔。
到此爲止,一個Class Object究竟佔用多少內存空間,已經完全說清楚了。但是,這只是針對單獨類,或者說是基類適用。對於子類,卻不一樣了。有興趣的朋友可以做一些實驗。
《C++ 類裏面,函數佔用存儲空間問題 》
先看兩段代碼:

代碼段1:
class A
{
public:
int print(){ cout<<"This is A"<
};
inr main()
{
A a;
cout << "Size of A = " << sizeof(a) << endl;
}

輸出結果:
Size of A =1

代碼段2:

class A
{
public:
int print1(){ cout<<"This is A"<
int print2(){ cout<<"This is A"<
int print3(){ cout<<"This is A"<
};
inr main()
{
A a;
cout << "Size of A = " << sizeof(a) << endl;
}

輸出結果:
Size of A =1
對象的大小是它的數據成員所佔存儲空間之和,就和結構體一樣。類中的函數是所有該類對象通用的方法,不算作對象的成員,因此也不算在對象的存儲空間內
問題:類裏面不管有多少個函數,這個類的對象只佔1個字節的內存。這個字節的內存的內容是什麼?是指針嗎?指針不是佔4個字節嗎?
當類中類有定義任何變量的時候,類的對象都是1個字節的,當類中沒有任何變量的時候,這個類裏沒有任何真正的成員變量,所以大小應該是0,但0大小不好在內存中定位一個地址,所以,就規定它大小爲0的對象要佔一字節空間,以便讓它擁有一個合法的地址。如果是有派生類的,還有考慮到內存對齊的問題的。

另外涉及到虛函數的話又不一樣了。如
class A
{
public:
virtual int print(){ cout<<"This is A"<
};
如果sizeof(A)的話,得出的是4。
原因是涉及到虛函數的實現問題。
class Class1
{
    m_data1;
   m_data2;
  virtual vfunc1()
  virtual vfunc2()
  virtual vfunc3()
};
Class1對象實例
通過vptr指針找到虛函數表
vptr
m_data1
m_data2
Vtable(虛函數表)
(*vfunc1)()
(*vfunc2)()
(*vfunc3)()
 
Class1::vfunc1()
Class1::vfunc2()
Class1::vfunc3()
所以回到原來的問題,A中只有一個或者幾個虛函數的話,沒有成員變量,那麼類A相當於含有一個vptr指向虛函數表的指針,所以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。

from:http://blog.csdn.net/chinabinlang/article/details/8614649
發佈了31 篇原創文章 · 獲贊 24 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章