C C++内存对齐以及特殊类的大小

news2024/10/5 7:16:49

目录

C语言

内存对齐现象

C语言中结构体的大小往往不是结构体中各种数据类型的加和,因为存在内存对齐;

struct S
{
    double d;//8字节
    char c;//1字节
    int i;//4字节
};
int main() {
    
    cout << sizeof(S) << endl;//输出S结构体的大小
    return 0;
}

运行结果:

在这里插入图片描述

S结构体大小是16字节,显然不是结构体内部各类型加和的8+1+4=13字节;

内存对齐规则

  1. 结构体的第一个成员在与结构体变量偏移量为0的地址处。
  2. 其他成员变量的偏移量要对齐到对齐数整数倍的地址处

对齐数: min(编译器默认的一个对齐数, 该成员类型大小 );

VS中默认的值为8 Linux中的默认值为4,这个默认对齐数可以用#pragma pack(num)预处理指令进行修改

  1. 结构体总大小最大对齐数每个成员变量确定选出的较小对齐数中最大的那个对齐数字)的整数倍

    注意,最大对齐数不一定包含VS平台那个默认8字节对齐数,假设每个成员大小都小于8,那么最大对齐数就是那些成员中最大的类型值

下面分析S结构体为何大小为16字节:

在这里插入图片描述

为什么存在内存对齐

性能原因:

CPU的优化规则

与CPU命中率有关,大致原则是这样的:对于n字节的元素(n=2,4,8,…),它的首地址能被n整除,才能获得最好的性能。

访问未对齐的内存,处理器需要作两次内存访问而对齐的内存访问仅需要一次访问

所以内存对齐本质上是一种空间换时间的优化;(现代内存空间大大的多,更偏向注重时间效率了)

小tips: 根据内存对齐的特征,设计结构体时,同样个数与类型的变量,让较小的成员聚集在一起可以节省空间!

如果struct or class中存在成员函数时的大小

struct S //class S
{
    char c;//1字节
    int i;//4字节
    double d;//8字节
    void fun() { cout << 1 << endl; }
    void fun2() { cout << 1 << endl; }
    void fun3() { cout << 1 << endl; }
};
int main() {

    cout << sizeof(S) << endl;
    return 0;
}

运行结果:
在这里插入图片描述

可以看到大小还是16字节,这是因为不管有多少成员函数,每个函数的地址都是只有一份且存放在内存中的.text只读代码段的,这是一种省空间的做法;

试想,如果函数的地址和普通变量一样开空间放在每个实例化的对象中,那么同一个结构体或者类实例化n个对象,难道要多出n个指向相同函数的函数指针来调用吗,显然这样是浪费空间的,各个实例化的对象因为是同一种类型,调用的都是同一个函数,一份就够了;

C++中引入了class类的概念,类同样与struct结构体一样遵守内存对齐规则,但是因为类可能具有虚函数表指针,这个需要拉出来单独分析;

空类大小为1

在这里插入图片描述

  1. 空类同样可以被实例化,为了区分空类实例化出来的不同对象, 那么就要保证每个实例能放入内存中的唯一地址;

  2. 如果这个类的大小为0的话无法放入内存!所以C++会强制给空类一个缺省成员,大小为1字节(跟个char一样);

如果有该空类有了自定义的成员变量,那么成员变量将取代顶替掉这个缺省成员

C++

class存在虚函数时的大小

在这里插入图片描述

原因:

C++中的虚函数是为了通过继承实现多态的一种设计;

如果一个类中存在虚函数,那么这个类的成员隐式的多了一个指针,这个指针叫虚表指针,它指向了一张虚表(数组)的首地址,因此大小是4or8字节(取决于32位还是64位);这个虚表里面存的是各个对应的虚函数的地址(多态的底层原理,这里不深究);

每个实例化对象存一份虚表指针的意义是,多态通过基类的指针或者引用调用不同的派生类方法时候,是通过通过这个虚表指针达到的多态的效果

在这里插入图片描述

通过观察可以发现,无所增加多少虚函数,该类的类型大小都不会变,只是多了一个虚表指针,因为增加的虚函数也是存放在.text代码只读段,地址可以通过虚表指针找到,不用在每个实例对象中都存一份!

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

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

相关文章

Linux常用系统日志

文章目录一 常用系统日志二 系统日志优先级三 其他日志文件一 常用系统日志 日志文件用途/var/log/messages记录大多数系统日志信息&#xff0c;包括启动、IO错误、网络和程序等问题/var/log/secure记录安全和身份验证等相关消息和错误/var/logrsyslog将所有日志文件写入到该目…

Nacos 漏洞利用

Nacos 漏洞利用 1.漏洞描述&#xff1a; Alibaba Nacos是阿里巴巴推出来的一个新开源项目&#xff0c;是一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。致力于帮助发现、配置和管理微服务。Nacos提供了一组简单易用的特性集&#xff0c;可以快速实现动态…

ASP.NET企业智能办公OA系统源码带文档【源码免费分享】

ASP.NET企业智能办公OA系统源码带文档 需要源码学习可私信我获取&#xff01; 本系统特色功能&#xff1a; 1&#xff1a;自定义工作流程&#xff0c;系统所有参数可自定义配置&#xff0c;支持多分公司、多部门架构 2&#xff1a;采用三层结构设计软件&#xff0c;系统扩容性…

vivo 实时计算平台建设实践

作者&#xff1a;vivo 互联网实时计算团队- Chen Tao 本文根据“2022 vivo开发者大会"现场演讲内容整理而成。 vivo 实时计算平台是 vivo 实时团队基于 Apache Flink 计算引擎自研的覆盖实时流数据接入、开发、部署、运维和运营全流程的一站式数据建设与治理平台。 一、v…

【云边有个小卖部】阅读笔记

童年就像童话&#xff0c;这是他们在童话里第一次相遇。 那么热的夏天&#xff0c;少年的后背被女孩的悲伤烫出一个洞&#xff0c;一直贯穿到心脏。 刘十三被欺负得最惨&#xff0c;却想保护凶巴巴的程霜。 每当她笑的时候&#xff0c;就让他想起夏天灌木丛里的萤火虫&#xff…

2022年专业连锁行业研究报告

第一章 行业概况 专业连锁经营是一种商业组织形式和经营制度&#xff0c;是指经营同类商品或服务的若干个企业&#xff0c;以一定的形式组成一个联合体&#xff0c;在整体规划下进行专业化分工&#xff0c;并在分工基础上实施集中化管理&#xff0c;把独立的经营活动组合成整体…

力扣sql入门篇(七)

力扣sql入门篇(七) 1 查询近30天用户活跃数 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 #注意因为between是两端都包含,仅统计30天,因而间隔天数写成29天 SELECT activity_date day,count(distinct user_id) active_users FROM Activity WHERE a…

使用Windbg分析多线程临界区死锁问题分享

目录 1、多线程死锁场景及多线程锁的类型 1.1、发生死锁的场景说明 1.2、锁的类型 2、问题实例说明 3、使用Windbg初步分析 4、进一步分析死锁 4.1、使用!locks命令查看临界区对象信息 4.2、通过占用临界区锁的线程id找到目标线程 4.3、如何将!locks命令打印出来的临界…

# 分布式理论协议与算法 第二弹 ACID原则

ACID 原则是在 1970年 被 Jim Gray 定义&#xff0c;用以表示事务操作&#xff1a;一个事务是指对数据库状态进行改变的一系列操作变成一个单个序列逻辑元操作&#xff0c;数据库一般在启动时会提供事务机制&#xff0c;包括事务启动 停止 取消或回滚。 但是上述事务机制并不真…

(1分钟)速通ikdtree

Ikdtree算法来自fast-lio2 其中i是incremental的缩写&#xff0c;表示增量的kdtree。 ​ Ikdtree算法来自fast-lio2 其中i是incremental的缩写&#xff0c;表示增量的kdtree。 ​ Ikdtree算法来自fast-lio2 其中i是incremental的缩写&#xff0c;表示增量的kdtree。 ​ 编辑…

性能成本难两全?OpenMLDB 实时计算双存储引擎让你不必纠结(附测评报告)

内存和磁盘的双存储引擎架构 1.1 使用场景描述 OpenMLDB 的线上服务部分为了满足不同的性能和成本需求&#xff0c;提供了两种分别基于内存和磁盘的存储引擎。关于这两种存储引擎的使用考量&#xff0c;和推荐匹配场景&#xff0c;见如下表。 [外链图片转存失败,源站可能有防…

使用ES Term query查询时一定要注意的地方

文章目录一、Term query简介二、Term query和Match query对比1. 数据准备2. 使用Match query查询3. 使用Term query查询三、分词器修改字段值的场景1. 删除大多数标点符号2. 英文大写转小写3. 超过max_token_length部分单独拆分一、Term query简介 使用Term query可以根据精确…

【计算机模型机设计】8指令多周期(硬布线)MIPS CPU设计报告

2023年第一篇文章来咯~ 8指令多周期&#xff08;硬布线&#xff09;MIPS CPU设计报告一、设计概述&#xff08;基本类似于上一篇&#xff09;1.1设计目的1.2设计任务1.3设计要求1.4技术指标二、总体方案设计2.1主要功能部件2.2数据通路设计三、详细设计与实现3.1主要功能部件的…

Cookie 和 Session、实现用户登录逻辑

Cookie 和 Session一、回忆 Cookie二、理解会话机制 (Session)三、Cookie 和 Session 的区别四、核心方法4.1 HttpServletRequest 类中的相关方法4.2 HttpServletResponse 类中的相关方法4.3 HttpSession 类中的相关方法4.4 Cookie 类中的相关方法五、代码示例: 实现用户登陆5.…

转速传感器信号隔离变送模块PCB焊接方波信号输出

特点 转速传感器信号直接输入&#xff0c;方波信号输出正弦波、锯齿波信号输入&#xff0c;方波信号输出200mV峰值微弱信号的放大与整形不改变原波形频率&#xff0c;响应速度快电源、信号&#xff1a;输入/输出 3000VDC三隔离辅助电源&#xff1a;5V、12V、15V或24V直流单电源…

【学Vue就像玩一样】什么是计算属性?什么使监视属性?

目录 1.计算属性 2.监视属性 2.1监视属性 2.2深度监视 3.computed和watch的区别 本栏会细致的将Vue划分为两大模块&#xff0c;基础篇&#xff0c;进阶篇。想要顺利通关vue篇首先要拥有三剑客&#xff0c;当然node ajax法宝也会辅佐你通关的&#xff0c;在学习的途中如果遇…

【回答问题】ChatGPT上线了!给我推荐20个比较流行的自动驾驶算法模型

给我推荐20个比较流行的自动驾驶算法模型 当前比较流行的自动驾驶模型有&#xff1a; 卷积神经网络&#xff08;CNN&#xff09; 长短时记忆网络&#xff08;LSTM&#xff09; 自适应调和滤波器&#xff08;ADF&#xff09; 自适应估计滤波器&#xff08;AEF&#xff09; 线性…

Vue组件及组件之间的通信

目录 一、Vue脚手架的使用 1、通过命令行使用vue-cli的指令创建&#xff1a;vue init webpack 项目名称 2、使用webStorm软件&#xff1a;本质仍然使用vue脚手架 3、使用vue ui创建&#xff1a;vue提供的图形化的操作界面 二、Vue的组件和组件之间的通信 1、组件&#xff…

使用线性回归、LGBM对二手车价格进行预测

使用线性回归、LGBM对二手车价格进行预测 目录使用线性回归、LGBM对二手车价格进行预测说明数据导入、查看和清洗数据说明导入训练集导入测试集合并数据查看数据整体情况处理数据检查并处理缺失变量EDA年份和价格地区和价格前任里程和价格燃料类型和价格传动装置类型Mileage与价…

数据库 SQL 高级用法

目录 一、INSERT INTO SELECT 用法 二、逻辑控制语句 三、公式表表达式 四、存储程序 五、触发器 一、INSERT INTO SELECT 用法 INSERT INTO SELECT 语句从一个表复制数据&#xff0c;然后把数据插入到一个已存在的表中。 1、从一个表中复制所有的列插入到另一个已存在的表…