计算一个类对象的大小时的规律:

 1、空类、单一继承的空类、多重继承的空类所占空间大小为:1(字节,下同);

2、一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间的;

3、因此一个对象的大小≥所有非静态成员大小的总和(包括动态分配的变量...);

4、当类中声明了虚函数(不管是1个还是多个),那么在实例化对象时,编译器会自动在对象里安插一个指针vPtr指向虚函数表VTable;

5、虚继承的情况:虚继承的实现是通过一个虚基类指针列表;由于涉及到虚函数表和虚基表,会同时增加一个(多重虚继承下对应多个)vfPtr指针指向虚函数表vfTable和一个vbPtr指针指向虚基表vbTable,这两者所占的空间大 小为:8(或8乘以多继承时父类的个数);

6、在考虑以上内容所占空间的大小时,还要注意编译器下的“补齐”padding的影响,即编译器会插入多余的字节补齐;

7、类对象的大小=各非静态数据成员(包括父类的非静态数据成员但都不包括所有的成员函数)的总和+ vfptr指针(多继承下可能不止一个)+vbptr指针(多继承下可能不止一个)+编译器额外增加的字节。

非虚单继承实例如下:

class A

{

char k[3];

public:

virtual void aa()

{

};

};

class B:public  A

{

char j[3];

public:

virtual void bb()

{

};

};

class C:public  B

{

char i[3];

public:

virtual void cc()

{

};

};

//一个字节   按4字节对齐

4(指向虚函数的虚指针)+4(自己的数据成员) = 8

4(指向虚函数的虚指针)+4(自己的数据成员)+4(父类A的数据成员)=12

4(指向虚函数的虚指针)+4(自己的数据成员)+8(父类的数据成员)=16

非虚多继承实例如下:

 

重写函数f()

Base -->char 类型

Base1:4(指向虚函数的虚指针)+4(自己的数据成员) = 8

Base2:4(指向虚函数的虚指针)+4(自己的数据成员) = 8

Base3:4(指向虚函数的虚指针)+4(自己的数据成员) = 8

Derive: 4(Base1指向虚函数表的虚指针)+4(Base1继承的成员变量)+4(Base2指向虚函数表的虚指针)+4(Base2继承的成员变量)+3(Base1指向虚函数表的虚指针)+4(Base3继承的成员变量)+4(自己的数据成员)=28

1)虚函数表在最前面的位置。

2)成员变量根据其继承和声明顺序依次放在后面。

3)每个父类都有自己的虚表。

4)子类的成员函数被放到了第一个父类的表中。

5)内存布局中,其父类布局依次按声明顺序排列。

6)每个父类的虚表中的f()函数都被overwrite成了子类的f()。这样做就是为了解决不同的父类类型的指针指向同一个子类实例,而能够调用到实际的函数。

非虚继承的钻石继承:

红色的部分就是重复的部分,就会造成二义性

虚继承的钻石继承:

可以看出,少了重合的部分。但是,代价是增加了一个虚基类指针vbptr。

C++一个类对象的大小计算的更多相关文章

  1. C# 中利用反射机制拷贝类的字段和属性(拷贝一个类对象的所有东西付给另一个类对象,而不是付给引用地址)

    from:https://blog.csdn.net/poxiaohai2011/article/details/27555951 //C# 中利用反射机制拷贝类的字段和属性(拷贝一个类对象的所有东西 ...

  2. 对C++对象内存模型造成的影响(类/对象的大小)

    首先重新回顾一下关于类/对象大小的计算原则: 类大小计算遵循结构体对齐原则 第一个数据成员放在offset为0的位置 其它成员对齐至min(sizeof(member),#pragma pack(n) ...

  3. static 成员变量、static 成员函数、类/对象的大小

    一.static 成员变量 对于特定类型的全体对象而言,有时候可能需要访问一个全局的变量.比如说统计某种类型对象已创建的数量. 如果我们用全局变量会破坏数据的封装,一般的用户代码都可以修改这个全局变量 ...

  4. JVM —— Java 对象占用空间大小计算

    零. 为什么要知道 Java 对象占用空间大小 缓存的实现: 在设计 JVM 内缓存时(不是借助 Memcached. Redis 等), 须要知道缓存的对象是否会超过 JVM 最大堆限制, 假设会超 ...

  5. Java-确定一个类对象代表一个类还是接口

    package com.tj; public class MyClass implements Cloneable { public static void main(String[] args) { ...

  6. C++类对象大小的计算

    (一)常规类大小计算 C++类对象计算需要考虑很多东西,如成员变量大小,内存对齐,是否有虚函数,是否有虚继承等.接下来,我将对此举例说明. 以下内存测试环境为Win7+VS2012,操作系统为32位 ...

  7. Java对象大小计算

    这篇说说如何计算Java对象大小的方法.之前在聊聊高并发(四)Java对象的表示模型和运行时内存表示 这篇中已经说了Java对象的内存表示模型是Oop-Klass模型. 普通对象的结构如下,按64位机 ...

  8. 虚函数列表: 取出方法 // 虚函数工作原理和(虚)继承类的内存占用大小计算 32位机器上 sizeof(void *) // 4byte

    #include <iostream> using namespace std; class A { public: A(){} virtual void geta(){ cout < ...

  9. C++中虚函数继承类的内存占用大小计算

    计算一个类对象的大小时的规律: 1.空类.单一继承的空类.多重继承的空类所占空间大小为:1(字节,下同): 2.一个类中,虚函数本身.成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空 ...

随机推荐

  1. [HNOI2012]集合选数(状压DP+构造)

    题目要求若出现x,则不能出现2x,3x 所以我们考虑构造一个矩阵 \(1\ 2\ 4 \ 8--\) \(3\ 6\ 12\ 24--\) \(9\ 18\ 36--\) \(--\) 不难发现,对于 ...

  2. Java算法 -- 二分查找

    折半查找,要求待查找的序列有序.每次取中间位置的值与待查关键字比较,如果中间位置的值比待查关键字大,则在前半部分循环这个查找的过程,如果中间位置的值比待查关键字小,则在后半部分循环这个查找的过程.直到 ...

  3. go实现dgraph的各种操作

    go实现dgraph的各种操作 import "github.com/dgraph-io/dgo" import "github.com/dgraph-io/dgo/pr ...

  4. CF1153D Pigeon d'Or

    Description 给一棵树,每个点是子节点的最大值或最小值,将叶子节点填上整数,使这棵树的根最大. Solution 明显的\(dp\)题,代码很短. 分类讨论如下: 1.如果是叶子节点,\(d ...

  5. table的 noWrap 属性不换行

    nowrap是什么意思? HTML中td元素的nowrap属性表示禁止单元格中的文字自动换行. 但使用时要注意的是,td元素noWrap属性的行为与td元素的width属性有关. td元素中nowra ...

  6. postgreSQL可视化工具pgAdmin3 导入表结构和数据

    材料:.backup文件.postgreSQL(pgAdmin3) 1.新建一个数据库2.选中数据库右键还原,弹出框中选择本地计算机备份文件路径---->点击还原(选择一个修改时间最早和最晚的还 ...

  7. mac 连接linux服务器,用scp命令实现本地文件与服务器文件之间的互相传输

    mac连接linux服务器 打开终端,切换到root权限下,切换root权限命令:sudo -i 通过ssh命令连接linux服务器:ssh root@ip地址(root是账户名) 然后根据提示输入密 ...

  8. vs 开发 win32 程序,调出控制台窗口,方便调试

    设置方法 项目 -> 属性 -> 生成事件 ->后期生成事件 -> 命令行 中添加 editbin /SUBSYSTEM:CONSOLE $(OutDir)\$(Project ...

  9. uCos-II移值(一)

    os_cpu.h文件 该文件主要是完成操作系统使用的内部数据类型.常数以及宏的定义,这些都是与处理器平台密切相关的: 第一部分 以下部分定义了系统内部常用的数据类型,为了增加系统的可移植性,系统内核只 ...

  10. react native 子组件向父组件传值

    父组件:   引入子组件:import CheckBox from  '../checkbox';   父子之间交互通信,接受子组件的值 fn(val){this.setState({roleType ...