【深度探索C++对象模型读书笔记】【第3章】Data语意学

1、例子,用VS 2013编译器

#include<iostream>
using namespace std;

class X{};
class Y :public virtual X{};
class Z :public virtual X{};
class A :public Y, public Z{};

int main(){
	cout << sizeof(X) << endl;// 1
	cout << sizeof(Y) << endl;// 4
	cout << sizeof(Z) << endl;// 4
	cout << sizeof(A) << endl;// 8

	system("pause");
	return 0;
}

注意:空类有隐藏的1byte的大小,是被编译器安插进去的一个char,以使这一class的两个objects得以在内存中配置独一无二的地址。


2、类对象大小受到三个因素的影响:

1)语言本身所造成的额外负担。当语言支持virtual base classes时就会导致一些额外负担。

2)编译器对于特殊情况所提供的优化处理。

3)Alignment的限制。

3、virtual baseclass subobject只会在derived class中存在一份实例,不管它在class继承体系中出现了多少次。

4、  C++standard并不强制规定base class subobjects的排列顺序或不同存取层级的data members的排列顺序这种琐碎细节,它也不规定virtual function以及virtual base classes的实现细节。

5、 C++对象模型尽量以空间优化和存取速度优化来表现nonstatic data members,并保持和C语言struct数据配置的兼容性。它把数据直接存放在每一个class object中,对于继承而来的nonstatic data members,不管是virtual或nonvirtual base class也是如此。至于static data members则被放置在程序的一个global data segment中,不会影响个别class object的大小。

6、inlinemember function躯体内的一个data member绑定操作,会在整个class声明完成后才发生,而argument list中的名称还是会在它们第一次遭遇时被适当地决议resolved完成。请总是把nested type声明放在class的起始处。

7、C++ Standard要求,在同一个accesssection(private、public、protected)中,members的排列只需满足“较晚出现的members在class object中有较高的地址”这一条件即可。也就是说各个members并不一定的连续排列,alignment可能需要的bytes以及编译器可能合成一些供内部使用的data members都可能介于被声明的members之间。

8、C++ Standard也允许编译器将多个accesssections之中的data members自由排列,不必在乎它们出现在class声明中的次序。

9、每一个staticdata member只有一个实例,存放在程序的data segment之中。每次程序取用static member时,都会被内部转化为对该唯一extern实体的直接参考操作。

10、取一个staticdata member的地址,会得到一个指向其数据类型的常量指针,而不是指向其class member的指针。

11、如果两个类都声明了同一个静态数据成员,那么当它们放在程序的data segment时,会导致名称冲突。编译器会对每一个静态数据成员编码,有多少个编译器,就有多少种name-mangling做法,任何name-mangling做法都有两个重点:

1)一种算法,推导出独一无二的名称;

2) 万一编译系统或者环境工具必须和使用者交谈,那些独一无二的名称可被轻易推导回原先的名称。

12、欲对一个nonstaticdata member进行存取操作,编译器需要把class object的起始地址加上data member的偏移量offset。

13、  在C++继承模型中,一个derivedclass object所表现出来的东西,是其自己的members加上其base classes members的总和。C++ Standard并未规定derived class members和base classes members的排列顺序。在大部分编译器上,除virtual base class外,base class members总是先出现。

14、如果只有继承,没有多态,C++语言保证是:“出现在derivedclass 中的base class subobject有其完整原样性”。

15、加上多态后:

1)创建virtualtable,用来存放声明的每一个虚函数的地址。

2)创建vptr,提供执行期的链接,使每一个object能够找到对应的virtual table。 

3)加强construct,使它能为vptr设定初值,让它指向class所对应的virtual table。

4)加强destructor,使它能够抹消指向class相关virtual table的vptr。

16、多重继承的复杂度在于derivedclass和其上一个base class乃至上上一个base class之间的非自然关系,其主要问题发生在derived class objects和其第二或后继的base class objects之间的转换。对一个多重派生对象,将其地址指定给最左端base class的指针,情况将和单一继承相同,而第二个或后继的base class的地址指定操作则需要修改地址,加上或减去(若是downcast)介于中间的base class subobjects的大小。C++ Standard并未要求多重继承时derived class object中各个base class subjectes的排列顺序,目前各个编译器都是根据声明顺序来排列它们。

17、class内如果内含一个或多个virtualbass class subobjects,将被分割为两部分:一个不变局部和一个共享局部。不变局部总是拥有固定的offset,其数据用以指定共享局部的位置,可以直接存取;而共享局部表现的就是virtual base class subobject,其位置会因为每次的派生操作而变化,只可间接存取。各家编译器实现技术之间的差异就在于间接存取的方法不同。

18、取一个nonstaticdata member的地址,将会得到它在class的offset;而取一个static data member的地址或者取一个绑定于真正class object身上的data member的地址,将会得到该member在内存中的真正地址。



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值