《inside the cpp object model》 阶段性阅读总结(3)

第三章 数据的语义
章前阅读

提到两点:

编译器系统会添加一些数据成员去支持一些语言功能。
  Alignment requirements on the data members and data structures as a whole(不知道怎么翻译,大概意思就是数据成员对齐的需要)


第一节、绑定数据成员

主要是全局的对象和类嵌套对象的绑定问题

首先是对象绑定,假如在一个内联函数里返回一个变量,如果全局定义了同名变量,并且在该函数的后面也定义了同名变量,那么较早一些的编译器会错误的返回全局变量。早期解决该问题的办法是使用安全的书写方式(把嵌套变量放到类的首部,或把内联函数的函数体写到类外)。现在的编译器会在整个类检查完之后再去绑定内联函数里的变量。
其次是内联函数的参数表,参数表(比如typedef来的变量类型)需要在检查到该函数的时候就去绑定变量,早期的编译器里,需要用户使用安全的书写方式,但后来的编译器会在发现类内的指派之后,将之前的指派设为false


第二节、数据成员的布局

非静态的数据成员会按声明的顺序存储在类对象里面,静态的数据成员会直接存储在程序的数据区里而与类对象无关。
在类的开始,编译器会插入一些对象去支持c++的对象模型,比如vptr。但是c++标准允许编译器将这些额外的东西存储在任意的地方,甚至于两个对象成员之间。
c++标准允许编译器去任意排列不同访问权限区域的对象成员,但是具体的顺序是预编译器相关的,没有同一的标准。不过似乎没有编译器这么做。访问权限的标识符不占用空间。

第三节、数据成员的访问

静态数据成员

无论是通过指针还是对象,对静态数据成员的访问最终都会翻译为对该变量实例的直接访问,这也是唯一的完全相等的情况。
如果通过函数返回对象来调用静态成员会怎么样呢?cfront会丢弃这个函数而直接调用静态成员。不过后期的c++编译器会将该调用翻译为两步,函数调用和对静态数据成员的访问。
将静态数据成员放到代码区会引起发生冲突,如果两个类恰好定义了同名的静态成员。c++使用name-mangling来确保每个静态成员有唯一的名称。实现的方式是和编译器相关的。有两个方面需要注意:

算法要产生唯一的名字。
这个唯一的名字要很容易被转义回原始的名称。为了方便编译器与用户交流。


非静态的数据成员

非静态的数据成员被直接存储在类的对象里,并且只能通过隐式或者现实的类去调用它。
作者问了一个问题,通过指针去访问一个成员和通过类去访问一个成员,这两者有没有明确不同?如果是静态成员的话,会完全等价。但是如果是非静态成员的话,有一种情况会不等价:该类是继承自包含一个虚基类的继承链,并且该成员继承自链中的虚基类。因为这种情况下,我们无法在编译时确定指针指向的是哪个对象,需要在运行时确定。


第四节、继承和数据成员

没有多态的继承

直接继承,会把完整的父类对象存储到子对象里(而不是存储去掉对齐所需的花费后拼凑起来的对象)。之所以要存储一个完整的父类对象,是我们可能要通过子类的对象去访问父类的对象,或者我们需要把子类对象赋值父类对象,切割后的子类一定要是一个完整的父类。

带有多态的继承

编译器考虑将vptr放到类的开始或者结束。放到结束可以很好的兼容c语言。放到开始可以高效的支持多态,但是会失去对c的兼容。倒是到底哪个更好一些尚无定论。

多重继承

类似单继承,只不过多存储了几个父类对象

虚继承

多重继承带来的问题就是,可能导致重复的父类,也就是菱形继承问题。
虚继承解决了这个问题。编译器处理的方式为:将一个包含一个以上虚基类的子类拆为两个区域,一个不变的区域,一个共享的区域,不变的区域里存储的是可以直接访问的数据成员,共享区域里存储虚基类的子类。
接下来就是访问问题,如何访问这些虚基类呢?cfront的做法是存储每一个虚基类的指针。
这个做法带来两个问题:

直接继承的虚基类的数量不同,子类的花费不一样。(空间)
随着继承链的增长,这个间接访问的深度也会增加。(时间)

对于第一个问题,有两个解决方案

微软的解决办法是引入虚基类表。(作者说,似乎只有微软的编译器是如此实现的)
第二个问题是bjarne喜欢的方法,他将虚基类的偏移量(不是地址)存到虚函数表里。

第五节、对象成员的效率

这一节是各种测试,按照书中所说,不感兴趣的话,直接跳入下一节。。。于是我就跳了。。。

第六节、指向成员的指针

指针和效率,依然谈到了效率。。先跳过,等我感兴趣了再来看吧。。

原文链接: https://www.cnblogs.com/dk647/archive/2011/05/03/2035892.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    《inside the cpp object model》 阶段性阅读总结(3)

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/24871

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月8日 上午2:46
下一篇 2023年2月8日 上午2:46

相关推荐