创世网站建设公司,贪玩游戏原始传奇官网,厦门免费建立企业网站,建设网站的流程图一直想搞清楚类对象的数据成员和虚函数的内存布局#xff0c;今天刚好有时间#xff0c;所以就写了个demo查看了一下具体的内存布局情况#xff08;使用的编译器为微软的#xff09;。下面是自己demo的代码#xff1a;#include iostream
#include windows.h今天刚好有时间所以就写了个demo查看了一下具体的内存布局情况使用的编译器为微软的。下面是自己demo的代码#include iostream
#include windows.h//#pragma pack(4) //影响每个类对象对齐的字节数默认对齐到8字节
class A
{
public:virtual void Test1() {};int a;
};class B
{
public:virtual void Test2() {};int b;
};class C :public A, public B {
public:virtual void Test1() override{}virtual void Test2() override{}virtual void Test3() {};int c;
};void main()
{C *pC new C();pC-a 1;pC-b 2;pC-c 3;int size sizeof(*pC);int sizeA sizeof(A);int sizeC sizeof(C);A* pA pC;B* pB pC;int sizeA1 sizeof(*pA);bool bRet (pB pC);
}下面是代码执行的时候内存布局截图从截图可以得到以下结果派生类对象C首先包含了基类A对象的数据然后包含基类B对象的数据最后才是包含自己的数据成员。派生类C中包含了2个虚表一个虚表是指向基类A中的函数一个虚表是指向基类B中的函数。类C有2个虚表是因为它派生自两个基类。如果是单继承就只有一个虚表。还有一个知识点无法从图中得知如果派生类中包含自己的虚函数则这个函数会添加到第一个虚表的尾部。下面是代码执行的时候对象占用内存大小截图类A对象会占用的内存大小为16字节虚表指针8个字节数据成员a占用4个字节此时只有12个字节但是微软编译器默认是对齐到8字节的所以最终加上字节对齐整个类A对象占用的内存大小为16字节。类C对象占用的内存大小为40字节类A的部分占用16字节类B的部分占用16字节数据成员c占用4个字节此时只有36个字节根据字节对齐默认为8字节所以最终加上字节对齐整个类C占用的内存大小为40字节。如果将前面代码中的第四行代码“//#pragma pack(4)”的注释去掉将编译器字节对齐强制设为4字节此时各个类对象的内存占用大小会发生变化。具体如下类A对象会只占用12字节虚表指针8个字节数据成员a占用4字节刚好对齐到4字节类C对象会占用28字节类A对象12字节类B对象12字节数据成员C占用4字节刚好对齐到4字节对齐到4字节的内存占用大小截图下面是将pC类C对象的地址赋值给pA(类A指针)和pB(类B指针)以后pC,pA,pB具体值的截图从截图可知pA的值和pC的值相等这是因为类C的继承关系中类A是第一个基类所以在类C对象的内存布局中首先就是类A所占用的部分。pB的值-pC的值12字节这是因为类C的继承关系中类A是第一个基类类B是第二个基类所以在类C对象的内存布局中类B放在类A的后面只要把pC的地址加上类A占用的部分(12字节对齐到4字节就是pB的地址。根据上面的结果我们知道pB和pC虽然指向同一个对象但是他们的地址值不一样如果用pB和pC比较会返回true还是false呢下面是运行截图我们发现最终的比较结果为true,这个是因为编译器在比较两个指针的时候不是简单的对两个地址值进行比较如果发现两个指针所属的类有继承关系的时候会先进行转换然后再比较。