• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > C++对象内存分布详解(包括字节对齐和虚函数表)

C++对象内存分布详解(包括字节对齐和虚函数表)

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了c++对象数组,c++对象,c++面向对象程序设计,c++类与对象,深度探索c++对象模型等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

1、C++对象的内存分布和虚函数表:

C++对象的内存分布和虚函数表注意,对象中保存的是虚函数表指针,而不是虚函数表,虚函数表在编译阶段就已经生成,同类的不同对象中的虚函数指针指向同一个虚函数表,不同类对象的虚函数指针指向不同虚函数表。

2、何时进行动态绑定:

(1)每个类对象在被构造时不用去关心是否有其他类从自己派生,也不需要关心自己是否从其他类派生,只要按照一个统一的流程:在自身的构造函数执行之前把自己所属类(即当前构造函数所属的类)的虚函数表的地址绑定到当前对象上(一般是保存在对象内存空间中的前4个字节)。因为对象的构造是从最基类部分(比如A<-B<-C,A是最基类,C是最派生类)开始构造,一层一层往外构造中间类(B),最后构造的是最派生类(C),所以最终对象上绑定的就自然而然就是最派生类的虚函数表。

(2)析构函数的调用跟构造函数的调用顺序是相反的,它从最派生类的析构函数开始的。也就是说当基类的析构函数执行时,派生类的析构函数已经执行过,派生类中的成员数据被认为已经无效(包括派生类对象中的虚表指针)。假设基类中虚函数调用能调用得到派生类的虚函数,那么派生类的虚函数将访问一些已经“无效”的数据,所带来的问题和访问一些未初始化的数据一样。而同样,我们可以认为在析构的过程中,虚函数表也是在不断变化的,不断解绑定。

因此,在基类构造函数或者析构函数中调用虚函数,并不会绑定到派生类的实现上,因为在这两个函数执行时虚函数表指针指向的是基类的虚函数表。

3、C++中类的大小:

由 1 可知,C++对象中只保存非静态数据成员,成员函数和静态数据成员是存储在静态数据区的。

字节对齐(默认):

1、VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。

2、VC为了确保结构的大小为结构的字节边界数(即该结构中占用最大空间的类型所占用的字节数)的倍数,所以在为最后一个成员变量申请空间后,还会根据需要自动填充空缺的字节。

3、如果对齐字节数(#pragma pack(n)),那么

(1)各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数和n的较小值的倍数。

(2)结构的大小为结构中占用最大空间的类型所占用的字节数和n的较小值的倍数。

class A { 
 double d;
 static int i;
 void f() { std::cout << "A::f" << std::endl; }
}; // 8 byte,只有double数据成员占8字节,成员函数和静态数据成员不在对象中,而是在静态数据区


class B { 
 int i; //4
 double j;//8
 char k; //
}; // 24 byte,考虑字节对齐, 4 + 4 + 8 + 1 + 7, 蓝色的4是为了满足条件1,黑色的7是为了满足条件2。如果指定4字节对齐,4 + 8 + 1 + 3


class C { 
 virtual void f() { std::cout << "C::f" << std::endl; }
}; // 4 byte,虚函数表指针占4个字节


class D { 
};// 1 byte,没有成员变量的结构或类的大小为1,因为必须保证结构或类的每一 个实例在内存中都有唯一的地址
</div>

注:

1、如果有成员对象,直接把成员对象展开到外部对象中,然后按照字节对齐的规律求大小。

2、虚继承的内存分布为:虚类指针-》派生类成员数据-》基类成员数据。其对齐方案是:首先把派生类所有成员当成一个嵌套结构体形式,位于最下面的基类的数据成员要保证自己对齐(首地址整除自己的字节数),但是不用在最下面添加字节保证整体是边界长度的整数倍(因为基类成员共享,不能把派生类当成一个整体)。

3、如果对象中有数组,可以把数组展开到对象中,然后按照字节对齐的规律求大小。

4、为什么要进行字节对齐

计算机组成原理教导我们这样有助于加快计算机的取数速度,否则就得多花指令周期了。为此,编译器默认会对结构体进行处理(实际上其它地方的数据变量也是如此),让宽度为2的基本数据类型(short等)都位于能被2整除的地址上,让宽度为4的基本数据类型(int等)都位于能被4整除的地址上,以此类推。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数据。

备注:visual studio 2010是按照默认方式进行字节对齐的 32位gcc按照4字节最齐

以上就是小编为大家带来的C++对象内存分布详解(包括字节对齐和虚函数表)全部内容了,希望大家多多支持~

</div>
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • C++对象的浅复制和深复制详解及简单实例
  • C++对象内存分布详解(包括字节对齐和虚函数表)
  • C++中的对象数组详细解析
  • C++对象的动态建立与释放详解

相关文章

  • 2017-05-28C++中重载、重写(覆盖)和隐藏的区别实例分析
  • 2017-05-28c++实现strcat字符串连接库函数的方法详解
  • 2017-05-28C++中头文件的概念与基本编写方法
  • 2017-05-28C++设计模式编程中proxy代理模式的使用实例
  • 2017-05-28C++实现二维图形的傅里叶变换
  • 2017-05-28wince程序防止创建多个实例实现互斥作用
  • 2017-05-28VC枚举串口端口应用
  • 2017-05-28详解设计模式中的模板方法模式及在C++中的使用
  • 2017-05-28输出1000以内的素数的算法(实例代码)
  • 2017-05-28详解约瑟夫环问题及其相关的C语言算法实现

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • C语言按关键字搜索文件夹中文件的方法
    • C++设计类不能被继承的方法实例讲解
    • C/C++中运算符的优先级、运算符的结合性详解
    • 奇怪的C语言特性
    • c++内联函数(inline)使用详解
    • 基于C++ cin、cin.get()、cin.getline()、getline()、gets()函数的使用详解
    • C++/Php/Python/Shell 程序按行读取文件或者控制台的实现
    • 解读C++编程的相关文件操作
    • 考试排名
    • C语言中时间的基本用法小结

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有