《深度探索C++对象模型》读书笔记

第三章(The Semantics of Data)

一个空的class的大小并不为0;

class x {   };//sizeof(x) = 1;
即空的class并不是真的空,它有一个隐晦的1bytes,那是编译器安插进去的一个char,这使得这个class的两个objects得以在内存中配置独一无二的地址:

X a, b;
if(&a == &b) cout << "error" << endl;

class的大小受到三个因素的影响:

  • 语言本身所造成的额外负担,virtual(vptr)
  • 编译器对于特殊情况所提供的优化处理(比如空class中插入一个char)
  • Alignment的限制(对齐的限制)

注意:nonstatic data members和继承而来的nonstatic data members(不论是virtual或nonvirtual base class), 都会直接存放在每个class object之中。static data members,被放置在程序的一个global data segment中,不会影响个别的class object的大小,不管class产生多少个objects(直接或间接产生),static data members永远只存在一份实体。

Point3d origin, *pt = &origin;
(1)origin.x = 0.0;
(2)pt->x = 0.0
那么通过origin存取和通过pt存取,有差别吗?答案是有

每一个nonstatic data member的偏移量(offset)在编译时期即可获知,甚至如果member属于一个base class subobject也奕扬,因此存取一个nonstatic data member,其效率和存取一个C struct member获一个nonderived class的member是一样的。(1)可以确定编译期间就可以知道其是origin的x,固定的;(2)如果x是从virtual base class继承来的,那么pt指向哪一个class type?所以这个操作必须延迟到执行期,(vptr)才能知道。


静态成员在使用前必须要进行初始化,在class内进行定义,在class外进行初始化

class A{
public:
    static int x;
};
int A::x = 1;
注意初始化的方式,程序中使用使,使用A::x即可,如果考虑继承或者虚继承,也 永远记住:静态成员只有唯一一个实体(如果有继承不管使用base::x还是driverd::x得到值都是一个值

容易犯的一个错误是,把一个class分解为两层或更多层,有可能会膨胀所需空间。


多态的开销

多态会带来的开销:

  1. 每个 class有一个与之相关的vitual table(虚函数表),用来存放它所声明的每一个virtual functions的地址, table的元素数目通常是virtual functions的数目
  2. 在每一个class object中导入一个vptr,提供执行期间的链接,使每个object能够找到相应的virtual table
  3. 加强constructor函数,使它能够为vptr设定初值
  4. 加强destructor函数
对于单继承,base class和derived class的objects都是从相同的地址开始,其间差异在于derived object比较大,用以容纳它自己的nonstatic data members,
 dervied A;
 base *B = &A;让基类指针指向派生类很自然。但是如果base中没有虚函数,而derived中有虚函数,那么这种规则就可能被打破,因为derived object中有一个vptr,vptr的插入可能会打破内存布局,那么此时进行转换时,就需要编译器的介入。多重继承更是打破这种布局。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值