[读书笔记] 深入探索C++对象模型-第三章 Data语义学(上)

原创 2016年08月28日 17:01:53

注:以下部分图片来自原书

1. 关于类的大小,有三个因素会影响类的大小:

a. 语言本身所造成的额外负担,例如虚基类,相应的子类会存在某种形式的指针,或者直接指向虚基类子对象,或者指向一个存放着虚基类子对象地址或者偏移量的表格。又如,虚函数,继承自含有虚函数基类的子类会含有一个指向虚函数表的指针。总之这些都会增加类对象的大小。

b. 对齐操作,即为了使总线的传输效率达到最高,类大小会被进行对齐操作,调整为某一个数字大小的倍数,32位机器上,通常为4的倍数,也就是说,一个类的实际占用大小为3,那么会被调整为4,类似的东东。

例如以下例子:


c. 编译器对于特殊情况的优化处理,例如对于大小为1的虚基类,某些编译器会提供特殊的支持,在此种情况下,空的虚基类会被视为子类对象最开头的一部分,这样就不会占用任何额外的空间,在此模型下类Y和Z的大小如下:


注意虚拟继承中不管虚基类在继承体系中出现了多少次,它在子类中始终只有一份,这也是虚继承由来的原因之一,所以对于类A的大小,首先是虚基类X大小为1,加上Y的大小减去因虚基类X而配置的大小(因为虚基类在子类中只有一份,所以要减掉在Y中的大小),结果是4,同理Z的大小也是4,目前类A的大小是9,对齐后是12(VS2015中测试是8,估计是因为堆空虚基类进行优化了)。

2. 关于数据成员的存取。

a. 对于静态数据成员,使用指针操作和对象操作效率是一样的,例如:a.staticMember = 0和pA->staticMember = 0都会被转化成为:A::staticMember = 0,所以二者是一样的。另外,对一个静态成员取地址会得到相应类型的指针,而不是指向类成员的指针(关于类成员指针的概念后续会有详细记录)。

b. 对于非静态成员,通过类对象操作数据成员时,编译器会把类对象的起始地址加上类成员的偏移,例如:a._y=0.0,那么地址&a._y等于&a + (&A::_y - 1),(指向类成员的指针偏移量总是被加上1,这个之后会有详细记录),如果在子类中操作继承而来的虚基类(非虚基类的不会有间接性)的数据成员,需要进行一层间接性,这个之后会有详细的整理。

3. 对于操作a.x = 0.0和pA->x = 0.0在以下情况下效率是不一样的:当x来源于虚基类时,在编译期,我们无法pA的确切类型(只可能知道静态类型,而不知道动态类型),他可能指向某个基类,也可能指向某个子类,因此无法知道x确切的偏移位置,所以存取操作必须要延迟到执行期,经由一个额外的简介引导来解决。如果使用a,则不会存在这样的不确定性,因为a的类型是确定知道的,所以成员的偏移在编译期就是确定的。

注:关于指针的静态类型和动态类型,例如:

B b; //B public inheriance of A
A* pA = b;
此时pA的静态类型为A,动态类型为B,也就是说,静态类型时固定不可变的,而动态类型可变,实际上C++的多太机制就是通过父类指针指向不同的子类对象,变换其动态类型实现的。

后续会继续整理本章的其他内容。








版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

[读书笔记] 深入探索C++对象模型-第三章 Data语义学(中)

继续整理第三章的内容(以下部分图片来自于原书): 1. 在只有继承没有多态的情况下,子类是的内容就是父类加上子类特有的数据成员,例如,对于如下两个类,Point2d和Point3d,后者公有继承自前者...

[读书笔记] 深入探索C++对象模型-第三章 Data语义学(下)

整理第三章最后的部分内容,关于数据成员指针的,之前竟然没听过类数据成员指针一说,果然路漫漫其修远兮啊。 注:以下例子和图片来源于原书。 1. 数据成员指针是指指向类数据成员的指针,其内容为对应数据成员...

[读书笔记] 深入探索C++对象模型-第五章-构造、析构、拷贝语义学(上)

继续整理第五章的内容,关于累的三个重要函数:构造函数,析构函数,拷贝构造函数。注:以下部分图片来自原书 1. 无继承情况下的对象构造。 当类中存在虚函数时,编译器会对该类产生膨胀作用, 例如如下类: ...

[读书笔记] 深入探索C++对象模型-第二章《构造函数语义学》(下)

继续整理第二章节剩下的内容。 1. 对于明确d

[读书笔记] 深入探索C++对象模型-第五章-构造、析构、拷贝语义学(中)

继续整理第五章的内容,关于对象复制的。  对于默认的拷贝赋值操作符,在如下情况下不会表现出按位拷贝(bitwise copy:关于按位拷贝,实际就是不使用拷贝构造函数或者拷贝赋值操作符,这里的不使用是...

[读书笔记] 深入探索C++对象模型-第二章《构造函数语义学》(上)

整理一下第二章的内容,共之后参考回顾。注:以下部分图片来源于原书 1. 默认构造函数会在需要的时候被编译器产生出来,要注意字眼“需要的时候”,例如如下代码: class Bat{ public: ...

[读书笔记] 深入探索C++对象模型-第四章-Function语义学(中)

继续整理第四章的内容,注:以下部分图片来自于原文 1. 单继承情况下的虚函数调用:  对于多态虚函数的调用(通过基类指针或者引用),例如ptr->z();,需要知道两个信息:     a. ptr所指...

[读书笔记] 深入探索C++对象模型-第五章-构造、析构、拷贝语义学(下)

继续整理第五章剩下的内容,关于析构函数语义的。 1. 如果类没有定义析构函数,那么只有类中含有成员对象(或者本类的基类)拥有析构函数的情况下,编译器才会合成一个出来,否则析构函数被视为不要,也就不需要...

[读书笔记] 深入探索C++对象模型-第四章-Function语义学(下)

继续第四章的内容整理,这一部分也是第四章的最后一部分,是关于成员函数指针的,第三章下的内容整理是关于成员变量指针的,这个则是成员函数指针,二者可以互为参考。 1. 非虚成员函数指针(非静态)。 取一个...

[读书笔记] 深入探索C++对象模型-第四章-Function语义学(上)

开始整理第四章的内容,关于函数的东西。 1. 静态成员函数不可以是const的,原因是因为this指针,详细参考:http://blog.csdn.net/beyongwang/article/det...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[读书笔记] 深入探索C++对象模型-第三章 Data语义学(上)
举报原因:
原因补充:

(最多只允许输入30个字)