C++类成员内存分布详解

本文将探讨C++类中成员变量的内存分布情况,包括普通成员、静态成员、虚函数等不同情况下的内存布局。


一、基本成员内存布局

1. 普通成员变量

普通成员变量按照声明顺序在内存中连续排列(受访问修饰符和内存对齐影响):

class NormalClass {
public:int a;      // 4字节char b;     // 4字节(考虑int对齐)double c;   // 8字节char d;     // 8字节(考虑double 对齐)
};
// sizeof(NormalClass) = 24 (考虑对齐填充)

内存布局:

| 0-3: int a | 4: char b | 5-7: padding | 8-15: double c | 16: char d | 17-23: padding |

2. 带继承的内存布局

派生类的成员追加在基类成员之后:

class Base {
public:int base_var; // 4字节
};class Derived : public Base {
public:int derived_var; // 4字节,再加上Base 类的 4字节,总共8字节
};

内存布局:

| 0-3: Base::base_var | 4-7: Derived::derived_var |

二、静态成员的内存分布

静态成员不占用类实例的内存空间,存储在全局数据区

class WithStatic {
public:int normal_var;         // 占用实例空间static int static_var;  // 不占用实例空间
};
// sizeof(WithStatic) == sizeof(int)

三、虚函数对内存的影响

1. 含有虚函数的类

编译器会隐式添加虚表指针(vptr),通常放在对象起始位置,虚函数表(vtable)本身不占用类实例的内存空间,vtable 存储在程序的只读数据段(全局静态区),每个类(而非对象)共享一个 vtable。虚表指针(vptr)会占用类实例的内存空间,每个对象实例中存储一个指向 vtable 的指针,在 64 位系统中占用 8 字节,32 位系统中占用 4 字节:

class WithVirtual {
public:virtual void foo() {}  // 添加vptrint a;
};
// 在32位系统上sizeof(WithVirtual) == 8 (vptr + int)
// 在64位系统上sizeof(WithVirtual) == 16 (vptr + int + padding)

内存布局(64位系统):

| 0-7: vptr | 8-11: int a | 12-15: padding |

2. 继承体系中的虚函数

派生类与基类共享同一个vptr(单继承情况下):

class BaseWithVirtual {
public:virtual void foo() {}int base_var;
};class DerivedVirtual : public BaseWithVirtual {
public:virtual void bar() {}  // 添加到虚表int derived_var;
};

内存布局(64位系统):

| 0-7: vptr | 8-11: Base::base_var | 12-15: Derived::derived_var |

四、多继承的内存布局

多继承情况下,每个基类子对象按声明顺序排列:

class Base1 { public: int base1_var; };
class Base2 { public: int base2_var; };class MultiDerived : public Base1, public Base2 {
public:int derived_var;
};

内存布局:

| 0-3: Base1::base1_var | 4-7: Base2::base2_var | 8-11: derived_var |

五、验证内存布局的代码

#include <iostream>
#include <cstddef>#define PRINT_OFFSET(className, member) \std::cout << "Offset of " #member ": " \<< offsetof(className, member) << std::endlstruct Test {virtual void foo() {}  // 添加vptrint a;char b;static int c;
};int main() {std::cout << "Sizeof Test: " << sizeof(Test) << std::endl;PRINT_OFFSET(Test, a);  // 64位系统输出 8PRINT_OFFSET(Test, b);  // 64位系统输出 12return 0;
}

总结表格

特性是否影响实例大小存储位置
普通成员变量栈/堆
静态成员变量全局数据区
虚函数是(添加vptr)虚表
继承追加基类成员
虚继承更复杂布局

注意事项

  1. 实际内存布局可能因编译器实现不同而有所差异
  2. 使用 offsetof 宏验证偏移量
  3. 内存对齐可通过 #pragma pack 指令调整

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

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

相关文章

计算机视觉——为什么 mAP 是目标检测的黄金标准

概述 在目标检测领域&#xff0c;有一个指标被广泛认为是衡量模型性能的“黄金标准”&#xff0c;它就是 mAP&#xff08;Mean Average Precision&#xff0c;平均精确率均值&#xff09;。如果你曾经接触过目标检测模型&#xff08;如 YOLO、Faster R-CNN 或 SSD&#xff09;…

C语言单链表的增删改补

目录 &#xff08;一&#xff09;单链表的结构定义及初始化 (二)单链表的尾插&#xff0c;头插 (三)单链表的尾删&#xff0c;头删 (四)单链表的查找&#xff0c;删除&#xff0c;销毁 单链表是数据结构课程里的第二个数据结构。单链表在逻辑结构是连续的&#xff0c;在物理…

Android10.0 framework第三方无源码APP读写断电后数据丢失问题解决

1.前言 在10.0中rom定制化开发中,在某些产品开发中,在某些情况下在App用FileOutputStream读写完毕后,突然断电 会出现写完的数据丢失的问题,接下来就需要分析下关于使用FileOutputStream读写数据的相关流程,来实现相关 功能 2.framework第三方无源码APP读写断电后数据丢…

杀戮尖塔(Slay The Spire) 的全新角色模组 - 女巫

女巫&#xff08;The Witch&#xff09; 杀戮尖塔&#xff08;Slay The Spire&#xff09; 的全新角色模组 女巫模组为游戏增添了超过 75 张新卡牌和 4 个全新遗物&#xff0c;围绕 诅咒&#xff08;Curses&#xff09; 展开独特的玩法体验。她的起始遗物 黑猫&#xff08;Bl…

AI开发学习路线(闯关升级版)

以下是一份轻松版AI开发学习路线&#xff0c;用「闯关升级」的方式帮你从零开始变身AI开发者&#xff0c;每个阶段都配有有趣的任务和实用资源&#xff0c;保证不枯燥、可落地&#xff01;&#x1f447; 目录 &#x1f530; 新手村&#xff1a;打基础&#xff08;1-2个月&…

迭代器模式深度解析与实战案例

一、模式定义 迭代器模式&#xff08;Iterator Pattern&#xff09; 是一种行为设计模式&#xff0c;提供一种方法顺序访问聚合对象的元素&#xff0c;无需暴露其底层表示。核心思想是将遍历逻辑从聚合对象中分离&#xff0c;实现 遍历与存储的解耦。 二、核心组件 组件作用…

SSH远程工具

一、常见SSH远程工具 工具开源跨平台多标签文件传输高级功能价格Xshell❌Win✔️✔️脚本、会话管理免费/商业版Tabby✔️全平台✔️✔️插件扩展免费MobaXterm❌Win✔️✔️集成工具集免费/付费SecureCRT❌Win/macOS/Linux✔️✔️企业级加密$129+PuTTY✔️全平台❌❌基础连接…

VUE中的路由处理

1.引入,预处理main.ts import {} from vue-router import { createRouter, createWebHistory } from vue-router import HomePages from @/pages/HomePages.vue import AboutPage from @/pages/AboutPage.vue import NewsPage from @/pages/NewsPage.vue //1. 配置路由规…

编程助手fitten code使用说明(超详细)(vscode)

这两年 AI 发展迅猛&#xff0c;作为开发人员&#xff0c;我们总是追求更快、更高效的工作方式&#xff0c;AI 的出现可以说改变了很多人的编程方式。 AI 对我们来说就是一个可靠的编程助手&#xff0c;给我们提供了实时的建议和解决方&#xff0c;无论是快速修复错误、提升代…

Opencv计算机视觉编程攻略-第九节 描述和匹配兴趣点

一般而言&#xff0c;如果一个物体在一幅图像中被检测到关键点&#xff0c;那么同一个物体在其他图像中也会检测到同一个关键点。图像匹配是关键点的常用功能之一&#xff0c;它的作用包括关联同一场景的两幅图像、检测图像中事物的发生地点等等。 1.局部模板匹配 凭单个像素就…

C++内存管理优化实战:提升应用性能与效率

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家、CSDN平台优质创作者&#xff0c;高级开发工程师&#xff0c;数学专业&#xff0c;拥有高级工程师证书&#xff1b;擅长C/C、C#等开发语言&#xff0c;熟悉Java常用开发技术&#xff0c;能熟练应用常用数据库SQL server,Oracle…

17-产品经理-创建发布

点击“发布”-“创建发布”。 填写发布名称&#xff0c;选择测试的版本。还可以设置此次发布是否为“里程碑”。 点击“保存”后&#xff0c;进入该发布详情页面。需要为此次发布关联需求、已解决BUG、以及遗留BUG。可以通过设置条件&#xff0c;进行“搜索”&#xff0c;然后批…

Axure RP9.0教程 | 内联框架 对应html 元素中的iframe标签 (打开内部页面和外部网址)

文章目录 引言I 打开内部页面II 打开外部网址操作效果引言 应用场景: 选择右侧不同栏目,左侧内容发生变化 I 打开内部页面 在公用元件库中找到内联框架图标,将其拖到画布中,设置其宽、高;在右侧添加三个按钮,分别用来跳转三个不同的页面;在内部框架中,添加三个子页面,…

在1panel中安装WebUI

如果需要建站&#xff0c;那得选安装Openresty。点击应用商店&#xff0c;安装 Openresty 接下来安装Ollama&#xff0c;可以部署本地模型提供给WebUi平台使用 最后是安装 WebUi&#xff0c;安装时需要填写Ollama的地址: 容器地址&#xff1a;30000 这些安装都很方便&#xf…

项目难点亮点

Vue项目 RBAC设计 用户权限设置 WebSocket 消息处理 BPMN扩展 跨语言模型的调用 大片文件(影像,模型等,数据-模型集成) 组件&指令封装 低代码表单构建、BPMN编辑器集成与实现 通用参考点 若依(RuoYi)是一个基于 Vue.js 和 Spring Boot 的前后端分离权限管理系…

JVM生产环境调优实战

案例三&#xff1a;JVM频繁Full GC优化 1. 项目背景&#xff08;Situation&#xff09; 在云中万维跨境支付的反洗钱系统中&#xff0c;我们负责对海量交易数据进行实时规则校验&#xff0c;以确保符合监管要求。系统日均处理交易量超过500万笔&#xff0c;峰值QPS达到3000&a…

ASP.NET Web 中进行 GET/POST 提交并接收返回数据的几种方案

在 ASP.NET Web 应用程序中进行 GET 请求并接收返回数据可以通过多种方式实现&#xff0c;以下是几种常见的方法&#xff1a; 1. 使用 WebClient 类&#xff08;简单方式&#xff09; using System.Net; using System.IO;public string GetDataFromUrl(string url) {using (W…

Springboot--Kafka客户端参数关键参数的调整方法

调整 Kafka 客户端参数需结合生产者、消费者和 Broker 的配置&#xff0c;以实现性能优化、可靠性保障或资源限制。以下是关键参数的调整方法和注意事项&#xff1a; 一、生产者参数调整 ‌max.request.size‌ ‌作用‌&#xff1a;限制单个请求的最大字节数&#xff08;包括消…

Android学习总结之service篇

引言 在 Android 开发里&#xff0c;Service 与 IntentService 是非常关键的组件&#xff0c;它们能够让应用在后台开展长时间运行的操作。不过&#xff0c;很多开发者仅仅停留在使用这两个组件的层面&#xff0c;对其内部的源码实现了解甚少。本文将深入剖析 Service 和 Inte…

ExternalProject_Add 使用手册与文档详解

一、基本概念与语法 ExternalProject_Add 是 CMake 的一个核心命令&#xff0c;用于在构建过程中集成和管理外部项目&#xff08;如第三方库&#xff09;。它支持完整的生命周期管理&#xff0c;包括下载、配置、构建、安装和测试。 语法&#xff1a; ExternalProject_Add(&l…