C++对象内存分布详解(包括字节对齐和虚函数表)
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,因为必须保证结构或类的每一 个实例在内存中都有唯一的地址
注:
1、如果有成员对象,直接把成员对象展开到外部对象中,然后按照字节对齐的规律求大小。
2、虚继承的内存分布为:虚类指针-》派生类成员数据-》基类成员数据。其对齐方案是:首先把派生类所有成员当成一个嵌套结构体形式,位于最下面的基类的数据成员要保证自己对齐(首地址整除自己的字节数),但是不用在最下面添加字节保证整体是边界长度的整数倍(因为基类成员共享,不能把派生类当成一个整体)。
3、如果对象中有数组,可以把数组展开到对象中,然后按照字节对齐的规律求大小。
4、为什么要进行字节对齐
计算机组成原理教导我们这样有助于加快计算机的取数速度,否则就得多花指令周期了。为此,编译器默认会对结构体进行处理(实际上其它地方的数据变量也是如此),让宽度为2的基本数据类型(short等)都位于能被2整除的地址上,让宽度为4的基本数据类型(int等)都位于能被4整除的地址上,以此类推。比如有些平台每次读都是从偶地址开始,如果一个int型(假设为32位系统)如果存放在偶地址开始的地方,那么一个读周期就可以读出这32bit,而如果存放在奇地址开始的地方,就需要2个读周期,并对两次读出的结果的高低字节进行拼凑才能得到该32bit数据。
备注:visual studio 2010是按照默认方式进行字节对齐的 32位gcc按照4字节最齐
C++对象内存分布详解(包括字节对齐和虚函数表)的更多相关文章
- 【转载】图说C++对象模型:对象内存布局详解
原文: 图说C++对象模型:对象内存布局详解 正文 回到顶部 0.前言 文章较长,而且内容相对来说比较枯燥,希望对C++对象的内存布局.虚表指针.虚基类指针等有深入了解的朋友可以慢慢看.本文的结论都在 ...
- 图说C++对象模型:对象内存布局详解
0.前言 文章较长,而且内容相对来说比较枯燥,希望对C++对象的内存布局.虚表指针.虚基类指针等有深入了解的朋友可以慢慢看. 本文的结论都在VS2013上得到验证.不同的编译器在内存布局的细节上可能有 ...
- c++ 对象内存布局详解
今天看了的,感觉需要了解对象内存的问题.参考:http://blog.jobbole.com/101583/ 1.何为C++对象模型? 引用<深度探索C++对象模型>这本书中的话: 有两个 ...
- 好文章系列C/C++——图说C++对象模型:对象内存布局详解
注:收藏好文章,得出自己的笔记,以查漏补缺! ------>原文链接:http://blog.jobbole.com/101583/ 前言 本文可加深对C++对象的内存布局.虚表指针.虚 ...
- [Java]Java类和对象内存分配详解
描述 代码说明: 一.当Person p1 = new Person();第一次被调用时需要做两件事: 1.先判断类加载器是否加载过Person类,如果没有则加载到Person类型到方法区 2.在堆中 ...
- java内存分布详解
参见:http://blog.csdn.net/bluetjs/article/details/52874711 基本类型和引用类型.二者作为局部变量,都放在栈中,基本类型直接在栈中保存值,引用类型只 ...
- C++对象的内存布局以及虚函数表和虚基表
C++对象的内存布局以及虚函数表和虚基表 本文为整理文章, 参考: http://blog.csdn.net/haoel/article/details/3081328 http://blog.csd ...
- C++对象内存模型2 (虚函数,虚指针,虚函数表)
从例子入手,考察如下带有虚函数的类的对象内存模型: class A { public: virtual void vfunc1(); virtual void vfunc2(); void func1 ...
- C++对象内存模型2 (虚函数,虚指针,虚函数表)(转)
class A { public: virtual void vfunc1(); virtual void vfunc2(); void func1(); void func2(); virtual ...
随机推荐
- 如何优雅地学习计算机2<-->Helloworld
0.导入 在进行粗略的学习计算机底层知识和变量后,我们来开始编写年轻人的第一个程序--Helloworld. 我们需要用到的工具有:1.Dev-C++(也可以使用其他软件)2.脑子(最重要) ...
- 为什么 DNS 协议使用 UDP?只使用了 UDP 吗?
尽人事,听天命.博主东南大学硕士在读,携程 Java 后台开发暑期实习生,热爱健身和篮球,乐于分享技术相关的所见所得,关注公众号 @ 飞天小牛肉,第一时间获取文章更新,成长的路上我们一起进步 本文已收 ...
- Day14_84_通过反射机制修改和获取class里的属性值
通过反射机制修改和获取class里的属性值 * 属性对象.set(Object,属性值) 给Object对象中的某个属性赋值(属性对象) * 属性对象.get(Object); 获取Object对象中 ...
- Django+Vue+Docker搭建接口测试平台实战
一. 开头说两句 大家好,我叫林宗霖,是一位测试工程师,也是全栈测开训练营中的一名学员. 在跟着训练营学习完Docker容器技术系列的课程后,理所应当需要通过实操来进行熟悉巩固.正好接口自动化测试平台 ...
- B - Tempter of the Bone(DFS+剪枝)
The doggie found a bone in an ancient maze, which fascinated him a lot. However, when he picked it u ...
- 【Springboot】Springboot监听器Demo
/** * @author: yq * @date: 2020/8/31 0:01 * @description 自定义事件 */ @Data public class MyEvent extends ...
- 【手打】coredns单台使用
目录: coredns介绍 coredns安装 corendns配置 coredns介绍 CoreDNS 其实就是一个 DNS 服务,而 DNS 作为一种常见的服务发现手段,所以很多开源项目以及工程师 ...
- 从苏宁电器到卡巴斯基第09篇:我在苏宁电器当营业员 I
毕竟应聘的是营业员,门槛还是很低的 我应聘苏宁的时候已经到了2009年的8月初,记得当时苏宁电器的长春总部还在吉林大路与东盛大街交汇处的亚泰广场,我当时的面试就是在那里. 我记得很清楚,那天等待面试的 ...
- Android Studio导入Android 4.4.4r1的源码
本文博客地址:http://blog.csdn.net/qq1084283172/article/details/70339471 一.环境配置 1.ubuntu 14.04.5 x64bit 2.j ...
- POJ1988(带权并查集,搬砖块)
题意: 可以这样理解,有n快方形积木,一开始都是单独的放到哪,然后有两种操作 1 M a b 把a所在的那一堆落到b所在那一堆的上面(一开始自己是一堆) 2 C a 问a下面有多少个积木 ...