C++对象内存模型

C语言中数据和处理数据的函数是分别定义,各个处理数据的函数实现相应各种算法。但是C++提供了类,可以实现较好的数据和处理数据的算法的封装性,这种封装性相比较C语言而言会带来一些成本,这主要受制于是C++对象为支持相应特性而实现的内存模型。
C++中分别有static和nonstatic两种数据成员,有static、nonstatic、virtual三种成员函数。对于一个类的对象的内存布局方式主要经过一下演变。

1、内存布局方式

简单对象模型

每个object是一系列的slots,每个slot保存的都是一个指针,指向每个member(包括所有的数据成员、成员函数)。所有的member按照声明的方式排列。

      / +-------+   -----> [non-static data member]
      | +-------+   -----> [static data member]
slots=| +-------+   -----> [static member function]
      | +-------+   -----> [non-static member function]
      \ +-------+   -----> [virtual member function]

这种简单模型中,可以避免不同member类型需要不同存储空间带来的问题,同时一个object的大小很容易计算出来。这种最简单的模型在成员指针的实现中有深入的应用。

表格内存模型

将data member全部放在一个表格中,包含data member的实际存储;member function放在另一个表格中,每一项为一个函数指针指向相应的成员函数。对于每个object的内存布局中,只包含两个指针分别指向这两个表格。
这种表格内存模型在实现C++的虚函数机制上是一个有效方案,目前的C++实现中也是基于这种方案。

2、C++对象内存布局

根据上述两种基本模型进行演变和发展,C++对象的内存布局的基本方式是:
- object包含所有non-static数据成员,static 数据成员和所有函数成员都不放在object对象内
- static数据成员放置在全局数据区
- non-virtual函数成员(分为static和non-static)与普通non-member函数相同,其中
- static直接调用
- non-static需要使用object的this指针调用
- virtual函数成员通过虚函数表格(virtual function table, vtbl)与虚函数表指针(virtual function pointer, vptr)来实现,bptr一般放置在object的首地址起始处

虚函数表指针(vptr)只有在类存在虚函数时才会由编译器添加,此时也会由编译器进行constructor、destructor和copy assignmeh运算符函数的设置。同时,存在虚函数的类生成的虚函数表,都会在第一项设置与该类相关联的type info信息,用来完成C++的RTTI特性。
上述内存布局的主要优点是空间利用率和存取时间的效率都较优。主要缺点就是,如果应用程序代码不曾改变,但是object的non-static数据成员有修改,那么由于object直接存储了这些数据成员,因此必须重新编译。
一个C++对象的内存布局大小主要由以下因素决定:
1. 类中定义的nonstatic数据成员的总和
2. 由于alignment需求编译器进行的padding
3. 为了支持virtual特性添加的额外负担(vptr和vbptr)

另外,C++对象为了支持多态特性,只能使用引用或者指针来完成,实际对象进行调用时是无法完成多态的。有三种实现方式:
1. 继承类指针隐式转换为基类指针
2. 基类指针调用虚函数
3. dynamic_cast和typeid运算符完成
下面分别针对不同使用情形下C++类对象的内存布局进行讨论。

无多态性的类

对于没有多态性质的类,可以是一个单独的类,或者private继承等为了实现“has-a”、“is implemented in terms of”,这种情况下,数据成员与函数成员与C语言的struct没有区别,数据成员访问相同,函数成员的调用也相同,效率也相同,因此,从这种意义上看C++没有为类的实现而引入额外的负担。

class A{
  int step = 0;};
class B : private A{
public:
    void mf1();
    void mf2();
private:
    int a;
    int b;
    //...其他数据成员
};

B的对象的布局如下:

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值