我是靠谱客的博主 清秀耳机,最近开发中收集的这篇文章主要介绍c++中包含empty virtual base class 类的sizeof结果分析背景答案解析后话,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
背景
类的继承关系如下
class Base{};
class First:public virtual Base{};
class Second:public virtual Base{};
class Top:public First,public Second{};
考虑如下运算的结果
sizeof Basic
sizeof First
sizeof Second
sizeof Top
答案
有两个版本的结果
版本1
sizeof Basic = 1
sizeof First = 8
sizeof Second = 8
sizeof Top = 12
sizeof Basic = 1
sizeof First = 4
sizeof Second = 4
sizeof Top = 8
解析
版本1
Basic大小为1:
编译器为了让Base这一空虚基类的每一个实例拥有不同的内存地址,也就是说为了区分Base的不同实例,向其中添加了一个影藏的char。
Base a,b;
if(&a != &b) //这一句就是添加char的动机
{
std::cout<<"a和b当然不是同一个实例";
}
这个就有趣了。
首先,毫无疑问子类中有基类的1个字节
其次,由于该类含有虚基类,所以编译器给它安插了一个指针(我们暂且叫做vptr),用来指向虚机类的地址(或者偏移量),指针在32位的应用中为4字节
最后,还有3字节是啥?这3字节用来内存对齐(alignment)。为了附和某些底层机制,数据结构最好为4的整数倍大小,这样程序的运行会得到最高的效率,所以这儿补充了 额外的3字节空内容。
这里有个问题:为啥First和Second也为空的类,就不用添加那一个char呢?我是这么理解的:对于编译器来说,First和Second中有一个vptr所以编译器不认为这两个类是空的,自然不用添加那一个char
Top的大小为12:
先明确虚基类的意义:虚基类确保继承链中只有该虚基类的一个唯一实例。也就是说Top中不会因为First和Second的两个分支而带来两个Base基类成分,所有分支共享一个Base实例。好,我们来算大小。
首先,唯一一个来自虚基类的成分,大小为1字节。
其次,First和Second中除去虚基类的成分各有4个字节。
最后,这时大小为9,补位又来了,补到12字节。
版本2
版本2源于编译器对empty virtual base class 的优化,摘抄一段《inside the c++ object model》的原文
Under this strategy, an empty virtual base class is treated as being coincident with the beginning of the derived class object; that is, it takes up no additional space.
这段话有点拗口,我是这么理解的:将虚基类”融合“进子类中,成为子类开头的一部分,之后为了标识这是一个继承了虚基类的类,则还得保留那个vptr,指向自己的开头。
所以我们再来看大小:
Base: 1字节,解释同上
First和Second:只有一个vptr一共4字节,此时不用补位
Top:包括First和Second,各4字节,Base已经融合到了First和Second中,不用再加,此时Top为8字节,不用补位。所以一共8字节。
后话
c++中有很多看似无法理解甚至看起来有点“脑残”的现象和规定。其实他们的出现都是有原因的,或是兼容性问题,或是语言实现本身的要求,亦或根本就是弄混了c++不同分支的规定,张冠李戴。但只要弄清这些由来,这些“脑残”的东西也就成了自然。一切都逃不过追本溯源!
最后
以上就是清秀耳机为你收集整理的c++中包含empty virtual base class 类的sizeof结果分析背景答案解析后话的全部内容,希望文章能够帮你解决c++中包含empty virtual base class 类的sizeof结果分析背景答案解析后话所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复