前幾天被問到,在C++裏建立一個空類什麼都成員沒有,它佔多大內存?我一下子懵掉了,還真沒想過這個問題。後來查了下資料終於明白了,且聽我慢慢道來。
首先我們看一下這個測試程序:
#include <iostream>
using namespace std;
class Test
{
};
main()
{
Test t;
cout<<"size :"<<sizeof(t)<<endl;
}
輸出結果是:size : 1。
爲什麼這個類什麼成員都沒有還要真用1個字節的內存呢?原來C++要求每個實例在內存中都有獨一無二的地址,空類也會被實例化,所以編譯器會給空類隱含的添加一個字節。這樣空類實例化之後就具有獨一無二的地址了。而一旦類中有了普通的成員變量,編譯器就不會給這個類添加一個字節了。可以驗證上例中在Test類中添加一個public的int x,則輸出結果是4.
第二,咱們再來看另外一種情況:帶有static成員變量和函數的類
#include <iostream>
using namespace std;
class Test
{
public:
static void hello(){}
static int x;
};
main()
{
Test t;
cout<<"size of Test:"<<sizeof(t)<<endl;
}
輸出結果是:size :1
這是因爲static成員獨立於任何對象而存在,不是類類型對象的組成部分。這裏對象佔用的內存是一個字節還是因爲編譯器隱含的添加了一個字節的緣故。
第三,普通成員函數和普通成員變量
#include <iostream>
using namespace std;
class Test1
{
public:
int x;
};
class Test2
{
public:
int x;
void hello(){}
};
main()
{
Test1 t1;
Test2 t2;
cout<<"t1 size :"<<sizeof(t1)<<endl;
cout<<"t2 size :"<<sizeof(t2)<<endl;
}
以上輸出結果是:t1 size: 4
t2 size: 4
這說明普通成員函數是不佔用類的內存空間,但是普通的成員變量會佔用類的內存。c++中所有函數都是放在代碼區的,不管是全局函數還是成員函數。
第四,看一下含有virtual成員函數的類:
#include <iostream>
using namespace std;
class Test1
{
public:
int x;
};
class Test2
{
public:
int x;
virtual void hello(){}
};
class Test3
{
public:
int x;
virtual void hello(){}
virtual void hello2(){}
};
main()
{
Test1 t1;
Test2 t2;
Test3 t3;
cout<<"t1 size :"<<sizeof(t1)<<endl;
cout<<"t2 size :"<<sizeof(t2)<<endl;
cout<<"t3 size :"<<sizeof(t3)<<endl;
}
以上輸出結果是:t1 size:4
t2 size:8
t3 size:8
由這個例子可以看出受虛函數的影響,Test2類所佔的內存增加了4個字節但是t3並沒有比t2多4個字節。爲什麼會是醬紫呢?這是因爲virtual成員函數(包括純虛函數)會佔用內存。類中會有一個vPtr指向虛函數表virtual table。不管有多少個虛函數,每個類中只有一個vPtr。所以不管有多少個虛函數他們只會佔用sizeof(vPtr)=4個字節的內存空間。
第五,派生類:派生類所佔的內存要加上基類所佔的內存!
#include <iostream>
using namespace std;
class Test1
{
public:
int x;
};
class Test2:public Test1
{
public:
int y;
};
main()
{
Test1 t1;
Test2 t2;
cout<<"t1 size :"<<sizeof(t1)<<endl;
cout<<"t2 size :"<<sizeof(t2)<<endl;
}
以上輸出結果是:t1 size: 4
t2 size:8
最後總結起來就是:
1,普通的成員函數不會佔用內存,但是普通的成員變量會佔用內存
2,static變量和函數不會佔用內存
3,virtual成員函數(包括純虛函數)會佔用內存,因爲會有一個vPtr指向虛函數表
4. 派生類需要加上基類所佔的內存
5. 對於空類,編譯器會自動添加一個字節