C++一个类对象的大小计算
计算一个类对象的大小时的规律:
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++一个类对象的大小计算的更多相关文章
- C# 中利用反射机制拷贝类的字段和属性(拷贝一个类对象的所有东西付给另一个类对象,而不是付给引用地址)
from:https://blog.csdn.net/poxiaohai2011/article/details/27555951 //C# 中利用反射机制拷贝类的字段和属性(拷贝一个类对象的所有东西 ...
- 对C++对象内存模型造成的影响(类/对象的大小)
首先重新回顾一下关于类/对象大小的计算原则: 类大小计算遵循结构体对齐原则 第一个数据成员放在offset为0的位置 其它成员对齐至min(sizeof(member),#pragma pack(n) ...
- static 成员变量、static 成员函数、类/对象的大小
一.static 成员变量 对于特定类型的全体对象而言,有时候可能需要访问一个全局的变量.比如说统计某种类型对象已创建的数量. 如果我们用全局变量会破坏数据的封装,一般的用户代码都可以修改这个全局变量 ...
- JVM —— Java 对象占用空间大小计算
零. 为什么要知道 Java 对象占用空间大小 缓存的实现: 在设计 JVM 内缓存时(不是借助 Memcached. Redis 等), 须要知道缓存的对象是否会超过 JVM 最大堆限制, 假设会超 ...
- Java-确定一个类对象代表一个类还是接口
package com.tj; public class MyClass implements Cloneable { public static void main(String[] args) { ...
- C++类对象大小的计算
(一)常规类大小计算 C++类对象计算需要考虑很多东西,如成员变量大小,内存对齐,是否有虚函数,是否有虚继承等.接下来,我将对此举例说明. 以下内存测试环境为Win7+VS2012,操作系统为32位 ...
- Java对象大小计算
这篇说说如何计算Java对象大小的方法.之前在聊聊高并发(四)Java对象的表示模型和运行时内存表示 这篇中已经说了Java对象的内存表示模型是Oop-Klass模型. 普通对象的结构如下,按64位机 ...
- 虚函数列表: 取出方法 // 虚函数工作原理和(虚)继承类的内存占用大小计算 32位机器上 sizeof(void *) // 4byte
#include <iostream> using namespace std; class A { public: A(){} virtual void geta(){ cout < ...
- C++中虚函数继承类的内存占用大小计算
计算一个类对象的大小时的规律: 1.空类.单一继承的空类.多重继承的空类所占空间大小为:1(字节,下同): 2.一个类中,虚函数本身.成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空 ...
随机推荐
- HF-01
胡凡 本书在第2章对C语言的语法进行了详细的入门讲解,并在其中融入了部分C+的特性. 第3-5章是 入门部分. 第3章 初步训练读者最基本的编写代码能力: 第4章对 常用介绍,内容重要: 第5章是 ...
- dgraph实现基本操作
dgraph实现基本操作 简单介绍 dgraph 是一个分布式图数据库 mutate 为一个突变, 一般认为添加数据或者是删除数据为一个突变 query 为一个查询 golang实现dgraph的基本 ...
- layui模板引擎
<在模板中调用js方法> 1.js代码 layui.define(['laytpl', 'jquery'], function (exports) { var $ = layui.jque ...
- dpdk之路-环境部署
dpdk实验环境部署 1.实验环境说明 vmware workstatioin 12 centos 7.5.1804 dpdk-stable-18.11.1 2.实验步骤 (1)虚拟机安装 http: ...
- Apache Hadoop 2.9.2 的HDFS High Available模式部署
Apache Hadoop 2.9.2 的HDFS High Available 模式部署 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 我们知道,当NameNode进程挂掉后,可 ...
- 机器学习在入侵检测方面的应用 - 基于ADFA-LD训练集训练入侵检测判别模型
1. ADFA-LD数据集简介 ADFA-LD数据集是澳大利亚国防学院对外发布的一套主机级入侵检测数据集合,包括Linux和Windows,是一个包含了入侵事件的系统调用syscall序列的数据集(以 ...
- Kubernetes之dashboard
部署dashboard $ wget https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommen ...
- STL仿函数functor
一:仿函数functor介绍 尽管函数指针被广泛用于实现函数回调,但C++还提供了一个重要的实现回调函数的方法,那就是函数对象. functor,翻译成函数对象,伪函数,算符,是重载了“()”操作符的 ...
- python之路(5)文件操作(open)
目录 前言 文件的打开模式 文件句柄的方法 seek()方法介绍 前言 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 f = open('demo.txt','r',e ...
- 五十六、linux 编程——UDP 编程模型
56.1 UDP 编程模型 56.1.1 编程模型 UDP 协议称为用户数据报文协议,可靠性比 TCP 低,但执行效率高 56.1.2 API (1)发送数据 函数参数: sockfs:套接字文件描述 ...