C++对象内存模型初探

本文探讨了C++中的虚继承和虚函数,分析了虚继承类对象的内存布局,包括虚表和虚指针的概念。通过实例展示了虚继承如何影响内存大小,并解释了内存对齐的作用。此外,还揭示了类对象内部成员变量和虚指针的存储顺序。
摘要由CSDN通过智能技术生成

前言

周末看资料的时候,看到虚继承和虚函数(两者完全不是一码事,正在写一个简单的总结),进一步看到C++的类对象的内存模型,网上已有很多文章,自己也记录一下。

简单模式

研究问题从简单入手,一步步深入。我们先来看一个最简单的模式;

class A{
public:
int a;
};

用测试程序可以发现,A的对象的大小是4字节,也就是a(int类型)的大小;
继承:

class E :public A
    {  
    public:  
        int e;  
    };

此时E的对象的大小就是8(2个成员a和e的大小),在内存中的分布也很明确,a(父类成员)在前,e(子类成员)在后

虚继承

下面来看虚继承的场景,先上代码:

class A  
    {  
    public:  
        int a;  
    };  
    class B :virtual public A  
    {  
    public:  
        int b;  
    };  
    class C :virtual public A 
    {  
    public:  
        int c;  
    };  
    class D :public B, public C 
    {  
    public:  
        int d;  
    }; 

首先来看各个类的对象占用的内存大小:
A, B, C, D:
4, 16, 16, 40

这里面涉及2个知识点,一个是虚指针和虚表,一个是内存对齐

虚表 虚指针

首先来看虚表和虚指针:
1、虚表和虚指针只有在虚继承的情况下才会有,普通(非虚继承)继承是没有的;
2、虚指针是占用对象的空间的,虚表则是对应到类的信息里,是不占用对象空间的;
先来解释为啥B和C的对象的内存大小是16,B(或者C);
先通过代码打印一下B的对象向的地址及其成员的地址:

A a;  
B b;
printf("&b = 0x%llx\n", &b);
printf("&b.a = 0x%llx\n", &b.a);
printf("&b.b = 0x%llx\n\n", &b.b); 

结果如下:

&b = 0x7ffeec7657b8
&b.a = 0x7ffeec7657c4
&b.b = 0x7ffeec7657c0

我们可以做出如下猜测,对B的对象而言,其内存布局如下:

vbptr;//虚指针,size=8(64位系统),0x7ffeec7657b8,也是该对象的起始地址
b; //继承自父类的成员变量,size=4(int),0x7ffeec7657c0
a; //子类自己的成员变量,size=4(int),0x7ffeec7657c4

而对D而言,其打印结果为:

&d = 0x7ffeee9d9780
&d.a = 0x7ffeee9d97a0
&d.b = 0x7ffeee9d9788
&d.c = 0x7ffeee9d9798
&d.d = 0x7ffeee9d979c

可推测其内存布局为:

vbptr_B;//虚指针,针对父类B的,size=8(64位系统),0x7ffeee9d9780,也是该对象的起始地址
b; //继承自父类B的成员变量,size=4(int),0x7ffeee9d9788
vbptr_C;//虚指针,针对父类C的,size=8(64位系统),0x7ffeee9d9790
c; //继承自父类C的成员变量,size=4(int),0x7ffeee9d9798
d; //子类自己的成员变量,size=4(int),0x7ffeee9d979c
a; //祖父类A的成员变量,size=4(int),0x7ffeee9d97a0

内存对齐

通过上面的打印信息可以看到,在类D的对象的成员地址的打印以及后续的内存模型推理上,我们发现:
b 和 vbptr_C 两者的地址分别是:0x7ffeee9d9788 和 0x7ffeee9d9790;但b的size只有4,为啥却缺了8呢?
这就是因为内存对齐,因为vbptr_B为8字节,为了与vbptr_B保持对齐,故b也占用了8个字节,而不是它自己的实际大小:4字节

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lqw198421

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值