前几天被问到,在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. 对于空类,编译器会自动添加一个字节