C++中虚函数继承类的内存占用大小计算
程序员文章站
2024-03-21 11:53:04
...
前半部分转自https://www.cnblogs.com/SeekHit/p/7570247.html
其中为32位字节对齐,后半部分给出自己的理解。
字节对齐的原理见链接https://www.cnblogs.com/0201zcr/p/4789332.html(注意64位系统虚函数指针占8字节,32位占4字节)
计算一个类对象的大小时的规律:
- 1、空类、单一继承的空类、多重继承的空类所占空间大小为:1(字节,下同);
- 2、一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间的;
- 3、因此一个对象的大小≥所有非静态成员大小的总和;
- 4、当类中声明了虚函数(不管是1个还是多个),那么在实例化对象时,编译器会自动在对象里安插一个指针vPtr指向虚函数表VTable;
- 5、虚承继的情况:由于涉及到虚函数表和虚基表,会同时增加一个(多重虚继承下对应多个)vfPtr指针指向虚函数表vfTable和一个vbPtr指针指向虚基表vbTable,这两者总共所占的空间大小为:8(或8乘以多继承时父类的个数);理解为虚函数表和虚基表分别占4字节。即基类的虚函数表总共占4个字节,子类的虚基表每个基类地址占4个字节
- 6、在考虑以上内容所占空间的大小时,还要注意编译器下的“补齐”padding的影响,即编译器会插入多余的字节补齐;
- 7、类对象的大小=各非静态数据成员(包括父类的非静态数据成员但都不包括所有的成员函数)的总和+ vfptr指针(多继承下可能不止一个)+vbptr指针(多继承下可能不止一个)+编译器额外增加的字节。
-
例子一
class A { }; class B { char ch; virtual void func0() { } }; class C { char ch1; char ch2; virtual void func() { } virtual void func1() { } }; class D: public A, public C { int d; virtual void func() { } virtual void func1() { } }; class E: public B, public C { int e; virtual void func0() { } virtual void func1() { } }; int main(void) { cout<<"A="<<sizeof(A)<<endl; //result=1 //64位为1 cout<<"B="<<sizeof(B)<<endl; //result=8 //64位为16 cout<<"C="<<sizeof(C)<<endl; //result=8 //64位为16 cout<<"D="<<sizeof(D)<<endl; //result=12//64位为24 cout<<"E="<<sizeof(E)<<endl; //result=20//64位为40 return 0; }
原帖中写到“求sizeof(D)的时候,需要明白,首先VPTR指向的虚函数表中保存的是类D中的两个虚函数的地址(只有一个虚基类地址指针),然后存放基类C中的两个数据成员ch1、ch2,注意内存对齐,然后存放数据成员d,这样4+4+4=12。”32位系统虚函数表指针内存是4字节,而64位系统虚函数表指针内存是8字节。所以在64位系统中结果不同于32位系统,过程为8+2+4对齐为8+8+4(8+8是满足父类的对齐要求)继续对齐为8+8+8满足(对齐为最大类型内存整数倍的对齐要求),故结果为24.
32位系统中求sizeof(E)的时候,首先是类B的虚函数地址,然后类B中的数据成员,再然后是类C的虚函数地址,然后类C中的数据成员,最后是类E中的数据成员e,同样注意内存对齐,这样4+4+4+4+4=20。
64位系统中求sizeof(E)的时候,首先是类B的虚函数地址(8字节),然后类B中的数据成员(并对齐为8+8=16字节),再然后是类C的虚函数地址(8字节),然后类C中的数据成员(8+1+1对齐为8+8=16字节),最后是类E中的数据成员e,同样注意内存对齐(8字节),这样16+16+8=40。
上一篇: python全栈核心提炼-第一章:python基础-语句
下一篇: 二、DDL 数据表