1. 程式人生 > >C++一個類佔多少個位元組

C++一個類佔多少個位元組

轉自http://www.tuicool.com/articles/uiUJry

一個空的class在記憶體中多少位元組?如果加入一個成員函式後是多大?這個成員函式儲存在記憶體中什麼部分?

一個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。這正好符合了,結論中的第三條:加上為了支援虛擬函式,產生的額外負擔。