C++内存布局

news2024/11/25 6:51:09

温故而知新,本文浅聊和回顾下C++内存布局的知识。

一、c++内存布局

C++的内存布局主要包括以下几个部分:

  • 代码段:存储程序的机器代码。
  • .数据段:存储全局变量和静态变量。数据段又分为初始化数据段(存储初始化的全局变量和静态变量)和未初始化数据段(存储未初始化的全局变量和静态变量)。
  • :用于动态内存分配。当你使用new或malloc函数时,内存会从堆中分配。
  • :用于存储局部变量和函数调用的信息(例如返回地址和参数)。当你调用一个函数时,一个新的栈帧会被压入栈,当函数返回时,这个栈帧会被弹出。
  • 常量段:存储常量字符串和其他常量。

代码示例

#include <iostream>

int global_var = 0;  // 初始化的全局变量,存储在初始化数据段
int uninit_global_var;  // 未初始化的全局变量,存储在未初始化数据段

void foo() {
    int local_var = 0;  // 局部变量,存储在栈
    static int static_local_var = 0;  // 静态局部变量,存储在初始化数据段
    int* dynamic_var = new int(0);  // 动态分配的内存,地址在堆,dynamic_var指针变量的生命周期是foo函数栈

    std::cout << "local_var: " << &local_var << std::endl;
    std::cout << "static_local_var: " << &static_local_var << std::endl;
    std::cout << "dynamic_var: " << dynamic_var << std::endl;

    delete dynamic_var;  // 释放动态分配的内存
}

int main() {
    std::cout << "global_var: " << &global_var << std::endl;
    std::cout << "uninit_global_var: " << &uninit_global_var << std::endl;

    foo();

    return 0;
}

二、C++ 类的内存布局

C++类的内存布局主要取决于类的数据成员和继承关系。以下是一些基本的规则:

  • 数据成员变量:类的数据成员按照它们在类定义中的顺序存储在内存中。每个数据成员的偏移量是它的类型对齐要求的倍数。
// x64
#pragma pack(push,4) //指定4字节对齐
class TmpClass{}; // 空类sizeof,大小为1

class NoVirtual
{
public:
    int m_i;    // 4字节
    double m_d; // 8字节
    shared_ptr<int> m_ptr; // 8字节 ==》64bit system ;4字节 ==》 32bit system
};
#pragma pack(pop) 
  • 成员函数:在C++中,成员函数并不直接存储在每个对象中。相反,所有对象共享同一个成员函数的副本。成员函数的代码存储在代码段,而不是每个对象的内存空间。因此,成员函数不影响类的sizeof大小。
    当你调用一个对象的成员函数时,编译器会自动将对象的地址作为隐藏参数传递给成员函数。这个隐藏参数通常被称为this指针。通过this指针,成员函数可以访问调用它的对象的数据成员。
class NoVirtual
{
    void dc(){}	// 成员函数,内存在代码段
public:
    int m_i;    // 4字节
    double m_d; // 8字节
    shared_ptr<int> m_ptr; // 8字节 ==》64bit system ;4字节 ==》 32bit system
};
  • 静态成员变量:静态成员变量不属于类的任何一个对象,它们在所有对象之间共享。静态成员变量存储在全局数据段,而不是对象的内存空间。

  • 静态成员函数:静态成员函数也不属于类的任何一个对象。它们没有this指针,因此不能访问类的非静态成员。静态成员函数的地址存储在代码段。

  • 继承:如果一个类继承自一个或多个基类,那么基类的数据成员会先于派生类的数据成员存储在内存中。如果有多个基类,那么基类的数据成员按照它们在类定义中的顺序存储。

class Iface
{
public:
    Iface(){MYTRACE();}
    virtual ~Iface(){MYTRACE();}
    virtual void Ifun() = 0;
};


// 继承
class MemLayout : public Iface
{
public:

    MemLayout(){ MYTRACE(); }
    ~MemLayout(){ MYTRACE(); }

    virtual void Ifun() override { MYTRACE(); }

    virtual void dc0(){ MYTRACE(); }
    virtual void dc1(){ MYTRACE(); }

private:
    int m_num = 0;
    static std::string m_desc;
};

std::string MemLayout::m_desc = "hello";

在这里插入图片描述

  • 虚函数:如果一个类有虚函数(virtual关键字修饰),那么编译器会为这个类生成一个虚函数表(vtable: 函数指针数组),并在每个对象中添加一个指向虚函数表的指针(vptr)。虚函数表中存储了虚函数的地址。如果一个类继承自一个有虚函数的基类,那么它会继承基类的虚函数表。
class VirtualClass
{
   virtual  void dc(){}
public:
    int m_i;    // 4字节
    double m_d; // 8字节
    shared_ptr<int> m_ptr; // 8字节 ==》64bit system ;4字节 ==》 32bit system
};

在这里插入图片描述

  • 虚继承:如果一个类使用虚继承,那么编译器会为这个类生成一个虚基类表(vbtable),并在每个对象中添加一个指向虚基类表的指针。虚基类表中存储了虚基类的偏移量。直白点说,虚继承的派生类的实例化对象,可是唯一指向了两张虚函数表的(下面有图为证)~
    请添加图片描述
class NoVirtual
{
    void dc(){}
public:
    int m_i;    // 4字节
    double m_d; // 8字节
    shared_ptr<int> m_ptr; // 8字节 ==》64bit system ;4字节 ==》 32bit system
};

class Iface
{
public:
    Iface(){MYTRACE();}
    virtual ~Iface(){MYTRACE();}
    virtual void Ifun() = 0;
};

// 虚继承
class MemLayout : virtual public Iface
{
public:

    MemLayout(){ MYTRACE(); }
    ~MemLayout(){ MYTRACE(); }

    virtual void Ifun() override { MYTRACE(); }

    virtual void dc0(){ MYTRACE(); }
    virtual void dc1(){ MYTRACE(); }

private:
    int m_num = 0;
    static std::string m_desc;
};

std::string MemLayout::m_desc = "hello";

在这里插入图片描述

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

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

相关文章

深入解析Guava范围类(Range)

第1章&#xff1a;范围类Range的重要性 大家好&#xff0c;我是小黑&#xff0c;今天咱们聊聊一个在Java编程世界里非常实用但又被低估的角色——Guava库中的Range类。你知道吗&#xff0c;在处理涉及到数值范围的问题时&#xff0c;Range类就像是咱们的救星。不论是判断某个数…

Redis设计与实现之订阅与发布

目录 一、 订阅与发布 1、 频道的订阅与信息发送 2、订阅频道 3、发送信息到频道 4、 退订频道 5、模式的订阅与信息发送 ​编辑 6、 订阅模式 7、 发送信息到模式 8、 退订模式 三、订阅消息断连 1、如果订阅者断开连接了&#xff0c;再次连接会不会丢失之前发布的消…

SiLM5350MDBCA-DG车规级隔离驱动芯片,我们能为汽车智能提供什么?

SiLM5350MDBCA-DG是一款适用于IGBT、MOSFET的单通道 隔离门极驱动器&#xff0c;具有10A拉电流和10A灌电流驱动能 力。提供内部钳位功能&#xff0c;可单独控制 上升时间和下降时间。 在 SOP8 封 装 中 具 有 3000VRMS 隔 离 耐 压 &#xff08; 符 合 UL1577&#xff09;。 与…

MySQL数据库 约束

目录 约束概述 外键约束 添加外键 删除外键 删除/更新行为 约束概述 概念&#xff1a;约束是作用于表中字段上的规则&#xff0c;用于限制存储在表中的数据。 目的&#xff1a;保证数据库中数据的正确、有效性和完整性。 分类: 注意&#xff1a;约束是作用于表中字段上…

使用 GBASE南大通用 ADO.NET

GBASE南大通用ADO.NET&#xff08;全称是 .NET Framework Data Provider For GBase&#xff09;提 供给.NET 应用程序访问 GBase 数据库、获取数据、管理数据的一套完整的解决 方案。 GBASE南大通用 ADO.NET 的四个核心类及若干功能类具有以下功能&#xff1a;  建立和管…

喜报|亚数荣获“2023物联网场景应用品牌企业”奖项

12月5日至6日&#xff0c;以“物联中国 数智雄安”为主题的“千企雄安行&#xff1a;2023物联网产业品牌大会”在雄安新区举办。 大会由雄安新区管理委员会、中关村发展集团股份有限公司、物联中国团体组织联席会主办&#xff0c;雄安新区投资促进服务中心、北京物联网智能技术…

layui框架实战案例(25):table组件筛选列记忆功能

即点击当前表格右上角筛选图标后&#xff0c;对表头进行显示隐藏勾选&#xff0c;再刷新页面依然保留当前筛选状态。 要实现layui表格组件的筛选列记忆功能&#xff0c;可以采取以下步骤&#xff1a; 存储筛选数据&#xff1a;当用户进行筛选操作时&#xff0c;将筛选的数据…

leecode-LCR 017. 最小覆盖子串(golang版本)

leecode最小覆盖字串 leecode链接地址 给定两个字符串 s 和 t 。返回 s 中包含 t 的所有字符的最短子字符串。如果 s 中不存在符合条件的子字符串&#xff0c;则返回空字符串 “” 。 如果 s 中存在多个符合条件的子字符串&#xff0c;返回任意一个。 题解 func minWindow(…

电脑屏幕怎么调大小?分享4个实用操作!

“我最近在使用电脑时总感觉电脑屏幕看起来不太对劲&#xff0c;好像字体被刻意放大了&#xff0c;看起来很不舒服&#xff0c;想问问有什么方法可以解决这个问题吗&#xff1f;” 电脑屏幕的正常显示是我们使用电脑的重要前提之一。如果电脑屏幕设置或显示不正确&#xff0c;会…

微信Windows版-无效的WeChatWin.dll文件,错误码126

更新的微信Windows最新版本&#xff0c;突然有一天打开微信提示“无效的WeChatWin.dll文件 错误码 ErrorCode:126,点击“确定”下载最新版本”。 卸载重新安装跟到windows目录下替换WeChatWin.dll皆无效 该解决方案适用于Windows系统&#xff1a;Windows7、Windows10、Windows…

ModuleNotFoundError: No module named ‘openai.error‘

ModuleNotFoundError: No module named ‘openai.error’ result self.fn(*self.args, **self.kwargs) File “H:\chatGPTWeb\chatgpt-on-wechat\channel\chat_channel.py”, line 168, in _handle reply self._generate_reply(context) File “H:\chatGPTWeb\chatgpt-on-wec…

JavaOOP篇----第四篇

系列文章目录 文章目录 系列文章目录前言一、Char类型能不能转成int类型&#xff1f;能不能转化成string类型&#xff0c;能不能转成double类型二、什么是拆装箱&#xff1f;三、Java中的包装类都是那些&#xff1f; 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;…

数据安全传输基础设施平台(二)

5安全传输平台总体设计 5.1 方案特点 规范化&#xff1a;严格遵循各种相关规范设计。独立性&#xff1a;系统各子系统间互相独立&#xff0c;在保持系统间接口的前提下&#xff0c;各系统间的升级互不干扰。最小耦合性&#xff1a;各子系统进行严格功能分解&#xff0c;每个子…

基于云主机的k8s环境搭建

1. 申请三台云主机(按量付费即可) 内网IP配置节点角色172.17.0.92C4Gk8s-master172.17.0.82C2Gk8s-node1172.17.0.172C2Gk8s-node2 2. 安装Kubernetes集群(全部节点执行以下操作) 关闭防火墙 systemctl stop firewalld systemctl disable firewalld关闭selinux sed -i s/e…

Android Studio(3.6.2版本)安装 java2smali 插件,java2smali 插件的使用方法简述

一、Android Studio&#xff08;3.6.2版本&#xff09;安装 java2smali 插件 1、左上角File—>Setting&#xff0c;如下图 2、Setting界面中&#xff1a;点击Plugins—>选择右侧上方Marketplace—>搜索栏输入java2smali&#xff0c;如下图 3、点击Install按钮—>点…

L1-053:电子汪

题目描述 据说汪星人的智商能达到人类 4 岁儿童的水平&#xff0c;更有些聪明汪会做加法计算。比如你在地上放两堆小球&#xff0c;分别有 1 只球和 2 只球&#xff0c;聪明汪就会用“汪&#xff01;汪&#xff01;汪&#xff01;”表示 1 加 2 的结果是 3。 本题要求你为电子宠…

文件拷贝记录丨电脑文件操作拷贝记录监控

最近在我们后台看到了一则这样的咨询&#xff1a; 问我们是否可以查看员工一天做了什么&#xff0c;电脑上打开了什么文件&#xff0c;电脑上的文件操作记录有哪些 叮咚&#xff0c;当然&#xff0c;我们的软件可以实现啦。 具体的操作步骤&#xff0c;我这里演示一下↓ 1、…

基于Java SSM框架实现体育竞赛运动会成绩裁判管系统项目【项目源码+论文说明】

基于java的SSM框架实现体育竞赛运动会成绩裁判管系统演示 摘要 体育竞赛是各种体育体育项目比赛的总称。是在裁判员的主持下&#xff0c;按统一的规则要求&#xff0c;组织与实施的体育员个体或体育队之间的竞技较量&#xff0c;是竞技体育与社会发生关联&#xff0c;并作用于…

Linux中ll -h和du -h 查看的文件大小,同一个文件du -h的结果大很多

当使用 ll -h 和 du -h 查看同一个文件的大小时&#xff0c;可能会看到两者的结果不同&#xff0c;这是因为它们计算文件大小的方式有所不同。 ll -h 的结果&#xff1a; ll -h&#xff08;或其完整形式 ls -lh&#xff09;会显示文件的大小&#xff0c;但这个大小可能只是文件…

JS的浅拷贝和深拷贝

首先理解什么是浅拷贝和深拷贝&#xff1a; 浅拷贝&#xff1a; 浅拷贝只会复制对象的第一层属性&#xff0c;而不会递归地复制嵌套的对象。浅拷贝仅复制对象的引用&#xff0c;新对象和原始对象仍然共享相同的引用&#xff0c;因此对新对象的修改可能会影响到原始对象。浅拷…