C++ 对象模型 | 关于对象

一、C++ 对象模型

1、对象内存布局

在C++中,有两种数据成员:staticnonstatic,以及三种成员方法staticnonstaticvirtual,下面从虚函数、非虚函数、静态成员变量、非静态成员变量等维度来分析,类对象的内存布局。例如:下面定义一个Point类,包含前面四种类型的成员

#include <iostream>
using namespace std;class Point
{
public:Point(double val);virtual ~Point();         // virtual function numbersdouble GetPoint();        // notstatic function numbersstatic int PointCount();  // static function numbers
private:double m_x;           // notstatic data numbersstatic int m_count;   // static data numbers
};int Point::m_count = 0;Point::Point(double val):m_x(val) {}
Point::~Point() {}
double Point::GetPoint(){ return m_x; }
int Point::PointCount(){ return m_count; }int main()
{Point pt(10.0);cout << sizeof(pt) << endl;  // 输出结果:16return 0;
}

一个实例对象中包含非静态数据成员虚表指针以及为对齐而必需的填充静态成员变量函数独立于单个实例化对象。

总结:影响C++对象大小的三个因素:非静态数据成员虚函数字节对齐

2、空对象

C++规定空类对象大小至少为1字节,只是为了区分实例化对象。如果创建了多个空类的对象,可以通过对象的内存地址区分。例如:下面创建一个空类Empty

#include <iostream>
using namespace std;class Empty
{
};int main()
{Empty e;cout << sizeof(e) << endl;  // 输出结果:1return 0;
}

3、数据成员的声明顺序与内存布局

3.1、声明顺序与内存布局

同一访问级别非静态数据成员声明顺序与内存中的布局是一致的(即:先声明的非静态数据成员,先分配内存地址)。不同访问控制级别的非静态数据成员,未规定内存分配顺序,但是实际上,编译是按照声明顺序来安排内存,例如:定义一个Point3d类,并打印出成员地址

#include <iostream>
using namespace std;class Point3D
{
public:void Print() const {cout << "this addr " << this << endl;cout << "m_x addr " << &m_x << endl;cout << "m_y addr " << &m_y << endl;cout << "m_z addr " << &m_z << endl;}private:int m_x;int m_y;int m_z;
};int main()
{Point3D obj;obj.Print();return 0;
}

输出结果

this addr 0x61fe14
m_x addr 0x61fe14
m_y addr 0x61fe18
m_z addr 0x61fe1cProcess returned 0 (0x0)   execution time : 0.241 s
Press any key to continue.

3.2、声明顺序对内存的影响

字节对齐要求,对不同大小字节的非静态数据成员的声明顺序有什么启发?例如:分别定义Point3DPoint3D_Extend类,两个类具有相关的非静态数据成员,但是声明顺序不一样,两个类对象占用的内存大小也不一样

#include <iostream>
using namespace std;class Point3D
{
private:int m_x;short m_w;int m_y;short m_v;
};class Point3D_Extend
{
private:int m_x;int m_y;short m_w;short m_v;
};int main()
{Point3D obj1;Point3D_Extend obj2;cout << "Point3D object size: " << sizeof(obj1) << endl;cout << "Point3D_Extend object size: " <<sizeof(obj2) << endl;return 0;
}

输出结果:

Point3D object size: 16
Point3D_Extend object size: 12Process returned 0 (0x0)   execution time : 0.241 s
Press any key to continue.

结论:相同大小的非静态数据成员放在一起,可以减少一个类对象内存占用

4、继承下的内存布局(非多态)

4.1、单继承内存布局

当把一个大的object赋值给小的object时,会引起object的切割,将大object的subobject赋值给小的object。C++保证出现在derived class中的base class subobject有其完整原样性(即:派生类对象中有一个完整的基类对象)。例如:分别定义Point2dPoint3d

#include <iostream>
using namespace std;class Point2D
{
protected:int m_x;short m_y;
};class Point3D : public Point2D
{
private:short m_z;
};int main()
{Point2D *p1, *p2;p1 = new Point2D;p2 = new Point3D;*p1 = *p2;  // 大的对象赋值给小的对象时,会引起对象的切割return 0;
}

4.2、多继承与多重继承的对象布局

多继承场景内存布局同单继承场景类似,如下:

在这里插入图片描述

5、继承下的内存布局(多态)

如果类中声明了虚函数,会给类对象创建一个虚函数指针,指向虚函数表。基类与派生类都有自己的虚函数指针、如果派生类不实现基类的虚函数,派生类的虚函数表相同索引位置存储的是基类的虚函数指针。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/622538.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

聚道云软件连接器助力知名企业,提升合同管理效率

一、客户介绍 某服饰股份有限公司是一家集服装设计、生产、销售及品牌建设于一体的企业。该公司的产品线涵盖男装、女装、童装等多个领域&#xff0c;设计风格时尚、简约、大方&#xff0c;深受消费者喜爱。公司注重产品研发&#xff0c;不断推陈出新&#xff0c;紧跟时尚潮流…

【linux笔记】vim

【linux笔记】vim 启动和退出 启动 vi退出 q强制退出 q&#xff01;编辑模式 vi foo.txt创建一个文件&#xff0c;启动后&#xff0c;是命令模式&#xff0c;是不能编辑的&#xff0c;键盘上的按键对应不同的命令。 插入模式 按键盘上的i&#xff0c;进入插入模式 保…

Redis(概述、应用场景、线程模式、数据持久化、数据一致、事务、集群、哨兵、key过期策略、缓存穿透、击穿、雪崩)

目录 Redis概述 应用场景 Redis的线程模式 数据持久化 1.Rdb&#xff08;Redis DataBase&#xff09; 2.Aof&#xff08;Append Only File&#xff09; mysql与redis保持数据一致 redis事务 主从复制&#xff08;Redis集群) 哨兵模式 key过期策略 缓存穿透、击穿、…

【大厂秘籍】 - Java多线程面试题

Java多线程面试题 友情提示&#xff0c;看完此文&#xff0c;在Java多线程这块&#xff0c;基本上可以吊打面试官了 线程和进程的区别 进程是资源分配的最小单位&#xff0c;线程是CPU调度的最小单位 线程是进程的子集&#xff0c;一个进程可以有很多线程&#xff0c;每条线…

UDS 诊断通讯

UDS有哪些车型支持 UDS(统一诊断服务)协议被广泛应用于汽车行业中,支持多种车型。具体来说,UDS协议被用于汽车电子控制单元(ECU)之间的通讯,以实现故障诊断、标定、编程和监控等功能。 支持UDS协议的车型包括但不限于以下几种: 奥迪(Audi)车型:包括A3、A4、A5、A6…

JDK8终将走进历史,Oracle宣布JDK继续免费

目录 前言Oracle 已免费提供 JDKOracle Java SE 产品最新动态 为什么业界中用JDK8那么多Java SE 8 公共更新结束总结 前言 今天想到上个月无意中听闻到的一句话&#xff1a;JDK8之后收费了&#xff0c;所以大家都用JDK8。当时只觉得这个话说得不对&#xff0c;但因为和说话的人…

Django数据库选移的preserve_default=False是什么意思?

有下面的迁移命令&#xff1a; migrations.AddField(model_namemovie,namemov_group,fieldmodels.CharField(defaultdjango.utils.timezone.now, max_length30),preserve_defaultFalse,),迁移命令中的preserve_defaultFalse是什么意思呢&#xff1f; 答&#xff1a;如果模型定…

点击随机红点的简单游戏(pygame)

import pygame import sys import random# 初始化 Pygame pygame.init()# 设置窗口大小 width, height 800, 600 screen pygame.display.set_mode((width, height)) pygame.display.set_caption("Click the Red Dot")# 定义颜色 black (0, 0, 0) red (255, 0, 0)…

Apache POI 导出Excel报表

大家好我是苏麟 , 今天聊聊Apache POI . Apache POI 介绍 Apache POI 是一个处理Miscrosoft Office各种文件格式的开源项目。简单来说就是&#xff0c;我们可以使用 POI 在 Java 程序中对Miscrosoft Office各种文件进行读写操作。 一般情况下&#xff0c;POI 都是用于操作 E…

浅谈 Raft 分布式一致性协议|图解 Raft

前言 大家好&#xff0c;这里是白泽。本文是一年多前参加字节训练营针对 Raft 自我整理的笔记。 本篇文章将模拟一个KV数据读写服务&#xff0c;从提供单一节点读写服务&#xff0c;到结合分布式一致性协议&#xff08;Raft&#xff09;后&#xff0c;逐步扩展为一个分布式的…

Android基于Matrix绘制PaintDrawable设置BitmapShader,以手指触点为中心显示原图像圆图,Kotlin(3)

Android基于Matrix绘制PaintDrawable设置BitmapShader&#xff0c;以手指触点为中心显示原图像圆图&#xff0c;Kotlin&#xff08;3&#xff09; 在 Android基于Matrix绘制PaintDrawable设置BitmapShader&#xff0c;以手指触点为中心显示原图像圆图&#xff0c;Kotlin&#…

读写分离的手段——主从复制,解决读流量大大高于写流量的问题

应用场景 假设说有这么一种业务场景&#xff0c;读流量显著高于写流量&#xff0c;你要怎么优化呢。因为写是要加锁的&#xff0c;可能就会阻塞你读请求。而且其实读多写少的场景还很多见&#xff0c;比如电商平台&#xff0c;用户浏览n多个商品才会买一个。 大部分人的思路可…

List集合遍历过程中修改元素(有坑)

说来惭愧&#xff0c;学 java 2年了&#xff0c;对 “Java是值传递” 这句话还没有理解它的精髓&#xff0c;以至于编程的时候出现了一些错误&#xff0c;这里记录一下。 一.问题再现 1.1将List集合中的每个字符串更改为其他值 1.2将List集合中的对象更改为其他对象 二.问题分…

extern static 在linux 和 qt下差别

从五个点来说 1.p3.h 中 静态定义一个const的int 变量并且赋值 2.p5.h 声明函数test2的定义 3. 直接extern 引用声明 test1() 函数 而不是像p5.h一样 把函数声明写到头文件 在别的.c文件直接包含头文件 第二点和第三点 是引用声明函数的两种用法 4.main函数 中static静态定…

修改Echarts图表的标题和副标题的内容

直接上代码 var graphicConfig [ { type: "text", left: "center", top: "center", style: { text: "包日", // 初始化为空字符串 textAlign: "center", fill: "#000", fontSize: 14, fontWeight: "bold&qu…

光猫(无限路由器)插入可移动硬盘搭建简易版的NAS

1.场景分析 最近查询到了许多有关NAS的资料&#xff0c;用来替代百度云盘等确实有很多优势&#xff0c;尤其是具有不限速&#xff08;速度看自己配置&#xff09;、私密性好、一次投入后续只需要电费即可等优势。鉴于手上没有可以用的资源-cpu、机箱、内存等&#xff0c;查询到…

计算机找不到msvcp120.dll如何解决?总结五个可靠的教程

在计算机使用过程中&#xff0c;遇到“找不到msvcp120.dll”这一问题常常令人困扰。msvcp120.dll作为Windows系统中至关重要的动态链接库文件&#xff0c;对于许多应用程序的正常运行起着不可或缺的作用。那么&#xff0c;究竟是什么原因导致找不到msvcp120.dll呢&#xff1f;又…

【设计模式】什么场景可以考虑使用简单工厂模式

1.概述 工厂模式是一种创建型模式&#xff0c;主要作用就是创建对象&#xff0c;将对象的创建过程和使用的过程进行解耦。我们平时说的工厂模式实际上是对三种不同类型的工厂模式的统称&#xff0c;简单工厂、工厂方法、抽象工厂&#xff0c;而在23种设计模式中&#xff0c;只…

深度学习笔记(六)——网络优化(2):参数更新优化器SGD、SGDM、AdaGrad、RMSProp、Adam

文中程序以Tensorflow-2.6.0为例 部分概念包含笔者个人理解&#xff0c;如有遗漏或错误&#xff0c;欢迎评论或私信指正。 截图和程序部分引用自北京大学机器学习公开课 在前面的博文中已经学习了构建神经网络的基础需求&#xff0c;搭建了一个简单的双层网络结构来实现数据的分…

机器学习~从入门到精通(三)梯度下降法

一、梯度下降法 # 梯度下降不是一种算法&#xff0c;是一种最优化方法 # 上节课讲解的梯度下降的案例 是一个简单的一元二次方程 # 最简单的线性回归&#xff1a;只有一个特征的线性回归&#xff0c;有两个theta # 二、在多元线性回归中使用梯度下降求解 三、### R…