C++ 虚基类表指针字节对齐模型

本文探讨了C++中虚基类表指针在类内存布局中的字节对齐问题。通过实例分析,作者揭示了在不同情况下虚基类表指针如何影响对齐规则,并提出了隐藏成员的对齐原则:隐藏成员的加入不应影响后续成员的对齐。通过对各种复杂场景的实验,作者总结出这一规律并验证了其正确性。
摘要由CSDN通过智能技术生成

关于虚基类表指针/虚函数表指针这些类里面的“隐藏成员”在结构里面是如何进行字节对齐的这个问题困惑了我48个小时。虽然网上也有很多关于虚继承、虚函数表、虚基类等内存布局的一些文章,但是基本上谈的都是大致的布局,什么地方有什么,按照什么顺序来排放等这些泛泛而谈的东西,好像都没有把字节对齐方面考虑进去的文章,或许他们都没有考虑到一些复杂层次的类继承关系,从而字节对齐的问题也没有成为问题,也自然而然地会被忽略掉,或者得出错误的对齐规则结论。


也许是我一开始就走错了路,在错误中越走越远,尝尽了各种曲扭的解决方案来回波折。我原以为我对字节对齐的规则已经很熟悉了,而恰恰是这仅仅几个字节的东西却困惑了我两三天,所以我觉得有必要将这个东西单独写一篇笔记,以记录我的研究成果和各种憋屈的时光。我们的目标是,精确到每一个字节~!

 

在Windows 里面微软是使用了虚基类表的方式来实现类的虚继承的,简单来讲就是当有虚继承的时候会在类里面加入一个“隐藏成员”虚基类表指针,这个指针就是指向虚基类表的了。我们要讨论的就是这个隐藏成员的字节级别的布局,其他的不在这里讨论。从现在开始我会一步一步地让事情变得更加复杂。


先看下面这片代码。在这里我使用了一个空类K,不要被这个东西所迷惑,我使用这个空类的目的主要是为了让它产生虚基类表指针而又不引入虚基类成员变量,这样我就可以少叙述一些关于虚基类成员排放的东西,而将焦点聚集在引入的那个虚基类表指针之上。这个空类虽然有点特殊,但是在这里它其他的东西和正常的类一样,不要纠结这个。还有,代码我直接指定了对齐参数,是为了不引起混乱。


#include"stdafx.h"
#pragma pack(8)
class K{};
 
class B :virtual K{
public:
       int b;
       B() :b(0xbbbbbbbb){}
};
 
 
int _tmain(int argc, _TCHAR* argv[])
{
       B aa;
       return 0;
} 


我们可以在IDE下打断点,用内存查看窗口轻易地观察到对象bb的内存布局情况,这个大家基本上都应该猜测得到大致的布局,就是在类B的开始插入了一个隐藏成员,虚基类表指针,然后才到B的成员b,因为虚基类没有成员所以其他的就不需要理了,这就是我选空类的原因,少说点话~。在VS2013下我抓到的布局是这样的:




恩,和我们猜测的一样。先是放了虚基类表指针然后才到 B 的成员。看到这里我们视乎可以得出点小结论,就是加入的隐藏成员,虚基类表指针,就是相当于在类里面加入一个正常的指针成员变量一样,即可以把类B看成是这样的等价布局:

class B { void *vb_ptr; int b;}


这样的话字节对齐等各方面都还算是合理的。

那么我们小改一下看下能推翻这个模型么。我们在B里面加一个成员变量double。变成这样:

 


                
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值