类的大小在面试的时候被问了, 这里记录备份一下.
类的大小计算的时候,只包括:
1 类的非静态成员数据的类型大小之和.
2 如果有虚函数的话,还要加上指向虚函数的指针(vptr)大小
3 边缘调整后的大小
4 与类中的构造函数,析构函数以及其他的成员函数无关.函数是类的所有对象共享的,而我们计算类的占用空间的时候,只计算对象占的空间
关于成员函数访问的问题:
内存对象模型里面仅保存变量,这里就包括指向虚表的指针,如果类定义里没有虚函数,那就没虚表什么事儿,_vprt会被优化掉,如果有,那么对象起始地址出就开始存放_vprt,如果涉及多个续表,"小伙伴,排排坐",之后的虚表指针接着第一个续表指针存放。
对于成员函数,如果调用成员函数,编译器会负责把已经生成好的成员函数首地址给要调用的对象。类对象.function()这个过程,会在编译期间直接把function的地址给类对象(就是说,会直接或间接的生成汇编代码,让类对象去call function函数。不会把调用的过程留到运行时去解决)。 而之前我犯糊涂,总想着得对象得有个指针来着。其实不必要,因为我们不会把问题留到运行时去确定。
我们去实验一下类大小的关系:
class a{}; class b{}; class c:public a{ }; class d:public b,public c{ }; class e:public a{ virtual void fun(){}; void My(){}; }; class f:public b,public c{ virtual void fun(){}; void MY(){}; }; class g{ public: int aaa; }; class h{ public: int aaa; char bbb; void My(){}; }; class i{ public: int aaa; char bbb; double ccc; }; class j{ public: int aaa; static int m; }; int j::m = 0;
假设有以上几个类,我们使用sizeof输出类的大小:
cout<<"sizeof a is : "<<sizeof(a)<<endl; cout<<"sizeof b is : "<<sizeof(b)<<endl; cout<<"sizeof c is : "<<sizeof(c)<<endl; cout<<"sizeof d is : "<<sizeof(d)<<endl; cout<<"sizeof e is : "<<sizeof(e)<<endl; cout<<"sizeof f is : "<<sizeof(f)<<endl; cout<<"sizeof g is : "<<sizeof(g)<<endl; cout<<"sizeof h is : "<<sizeof(h)<<endl; cout<<"sizeof i is : "<<sizeof(i)<<endl; cout<<"sizeof j is : "<<sizeof(j)<<endl;
得到的输出结果为
这里不难理解,a,b,c,d均没有成员变量和虚函数,这1个字节表明类的位置
e类有一个父类,类中有一个虚表指针4个字节,大小为4
f类有两个父类,类中有两个虚表指针,8字节,但是只有一个虚函数,而且看到内存中只有一个虚表指针的值,另一个没有值
(注:图中地址与上图地址不符,每次调试地址均会变化)
g类有一个成员变量占用4字节
h类有两个变量,一个int和一个char,这里和struct一样,内存对齐,占用8字节
i类是int,char,double排列,按8字节对齐,占用16字节
j类只有成员变量占用空间,静态成员不占用空间,为4字节
我们在输出对象的大小也是一样的
a A ; b B ; c C ; d D ; e E; f F; g G; h H; i I; j J; cout<<"sizeof a is : "<<sizeof(A)<<" Address of A is : "<<&A<<endl; cout<<"sizeof b is : "<<sizeof(B)<<" Address of B is : "<<&B<<endl; cout<<"sizeof c is : "<<sizeof(C)<<" Address of C is : "<<&C<<endl; cout<<"sizeof d is : "<<sizeof(D)<<" Address of D is : "<<&D<<endl; cout<<"sizeof e is : "<<sizeof(E)<<" Address of E is : "<<&E<<endl; cout<<"sizeof f is : "<<sizeof(F)<<" Address of F is : "<<&F<<endl; cout<<"sizeof g is : "<<sizeof(G)<<" Address of G is : "<<&G<<endl; cout<<"sizeof h is : "<<sizeof(H)<<" Address of H is : "<<&H<<endl; cout<<"sizeof i is : "<<sizeof(I)<<" Address of I is : "<<&I<<endl; cout<<"sizeof j is : "<<sizeof(J)<<" Address of J is : "<<&J<<endl;