现在的位置: 首页 > 综合 > 正文

深入探索C++对象模型 第三章 Data语意学

2018年04月13日 ⁄ 综合 ⁄ 共 1597字 ⁄ 字号 评论关闭
1、类对象大小受三个因素影响

a、virtual base和virtual function带来的vptr影响 
b、 EBO (Empty Base class Optimize)空基类优化处理,EBC(Empty Base Class)占用一个字节,其他含有数据成员的从EBC派生的派生类,只会算自己数据成员的大小,不受EBC一字节的影响 
c、alignment 字节对齐

2、Nonstatic data members在class object中的排列顺序将和其被声明顺序一样,任何中间介入的static data members都不会被放进布局之中。

3、静态成员变量 static data members

a、存放在程序的data segment之中 
b、通过指针和对象来存取member,完全一样,不管继承或者是虚拟继承得来,全局也只存在唯一一个实例 
c、静态常量成员可以在类定义时直接初始化,而 普通静态常量成员只能在.o编译单元的全局范围内初始化

4、非静态成员变量 nonstatic data members

a、 每一个nonstatic data member的偏移量在编译时即可获知 ,不管其有多么复杂的派生,都是一样的。通过对象存取一个nonstatic data member,其效率和存取一个C
struct member是一样的。
 
b、从对象存取obj.x和指针存取pt->x有和差异? 
     当继承链中有虚基类时,查找虚基类的成员变量时延迟到了执行期,根据virtual class offset查找到虚基类的部分,效率稍低 
     (成员变量的数据存取并没有this指针的变化)通过指针来存取成员变量会由于需要知道指向哪一种class type,所以很慢,而直接存取则不会

成员变量的具体分布详情参见C++内存分布

3.4 “继承”与Data Member

pc1_1=pc2;

*pc2_2=*pc1_1;

这一节内容很多,主要分了几个方面讨论不同情况下data member

1. 如果只有继承,没有多态,也就是没有虚函数,这里需要保证的是:“出现在derived class 中的base class subobject有其完整原样性”,因为子类的成员与基类的子对象绑在了一起,去填补空间,这样基类的子对象的原样性就会受到破坏。

2. 加上多态即虚函数后,首先是virtual table和vptr会创建出来,当然这个创建过程会影响到constructor,另外destructor也要相应修改。对于vptr的位置,不同的编译器会有不同的实现。

3. 对于多重继承,其对象的地址会指定给最左端的base class的指针,情况和单一继承相同,至于第二个或者猴急的基类的地址指定操作则需要将地址修改过

vertex3d v3d;

vertex *pv;

Point2d *p2d;

Point3d *p3d;

对于pv=&v3d的操作,内部转换为pv=(vertex*)(((char*) &v3d+sizeof(Point3d));

而对p2d、p3d赋值则不需要转换

另外也有某些编译器有不同的实现,但可以确定的是这样的class可能会有多个vptr。

4. 虚拟继承,基本思路也是引入一个新的指针,指向共享的内容。由于一般都比较麻烦,所以这里推荐的做法是virtual base class里面没有data member 每个继承虚基类的对象中都有一个指向虚基类的指针,这样能实现class的共享部分

3.5 对象成员的效率

大概的意思是打开优化开关后,都是差不多的,只有虚拟继承的效率比较差。另外都要靠测试来检验,没有什么经验可循。

3.6 指向Data Members的指针

每个data member都是有地址的,这里把这个地址取出来,然后进行操作,另外不同编译器还有差距,会有一个相差1的不同,所以就不研究这个问题了,求取对象的其实地址,如果其定义了x,y,z,则&z的地址-z的偏移值+1即可。

抱歉!评论已关闭.