C++对象的内存模型,对象是如何在内存中布局的?

1. 普通对象模型

对象是如何在内存中布局的?

成员 存放位置 访问范围
非静态数据成员 每一个对象体内 为该对象专有
静态数据成员 程序的静态存储区内,只有一份实体 为该类所有对象共享
成员函数(静态/非静态) 程序的代码段中,只有一份实体 为该类所有对象共享
类类嵌套的各种类型(typedef、class、struct、enum等) 与放在类外面定义的类型除了定义域之外没有本质区别 遵循类内部的访问规则

因此,构成对象本身的只有数据,类的成员函数不属于任何一个对象。非静态成员函数与对象之间的关系是通过this指针绑定的。

2. 增加继承和虚函数的类的对象模型

派生类的对象是如何在内存中布局的?

成员 规则
继承自基类的非静态数据成员 作为对象自己专用的数据
继承自基类的非静态成员函数 作为类的成员函数一样访问
虚函数(继承的或者新增的) 所有虚函数的地址都存放在vtable
多态类每一个对象中的vptr 函数指针的指针,指向所属类的vtable
继承自基类的vptr 继承和重用该vptr
多重继承的多个分支 每个分支都继承一个vptr并生成一个对应的vtable

vptr在派生类对象中的相对位置不会随着继承的层次改变而改变,一般编译器会将vptr放在所有数据成员的最前面。

为了支持RTTI,编译器会为每一个多态类创建一个type_info对象,并把其地址保存在该类vtable中的第一个位置。

3. vtable中虚函数指针的排列顺序

  1. 如果虚函数是第一次出现,则把它的函数地址指针依次插入到vtable的尾部。
  2. 如果派生类改写了基类的虚函数,则这个函数的地址在派生类vtable中的位置与其在基类vtable中的位置一直,而与其在派生类中的声明位置无关。也就是说一旦虚函数指针在vtable的位置确定,则它的位置就不会因为继承层次的改变而改变。
  3. 派生类没有改写的基类虚函数被继承,位置与原先在vtable中的位置相同。
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论