首页 > 系统相关 >C++ 类的内存布局

C++ 类的内存布局

时间:2024-03-01 21:23:25浏览次数:28  
标签:int double 布局 Derived C++ Base 内存 Offset baseConst

基类类内成员的内存分布

常见类内成员大致分为:类内变量、类内函数、静态变量、虚函数等,内存分布遵循:

  1. 所有成员会按照声明的顺序布局
  2. 类内成员会进行大对齐
  3. 类内函数不占用类的内存,存储在代码区
  4. 静态变量不占用类的内存,存储在全局/静态区
  5. 所有虚函数共用一个虚函数表指针,虚函数表指针不按声明顺序布局,如果有声明虚函数则虚函数表指针始终在类的内存地址的开始

例如:

#include <iostream>
using namespace std;

class Base {
public:
    short baseShort;
    int baseInt;
    char baseChar;
    const double baseConst;
    static int baseStaticInt;
    static const double baseStaticConst;
    virtual void baseFunc1() {}
    virtual void baseFunc2() {}
    Base() : baseConst(0.0) {} // 在构造函数中初始化 baseConst
};

int Base::baseStaticInt = 0; // 静态成员变量的定义
const double Base::baseStaticConst = 0.0; // 静态成员常量的定义

int main() {
    Base b;

    cout << "Size of Base class: " << sizeof(Base) << " bytes" << endl;

    // 计算偏移量
    cout << "Offset of baseShort: " << (char*)&b.baseShort - (char*)&b << endl;
    cout << "Offset of baseInt: " << (char*)&b.baseInt - (char*)&b << endl;
    cout << "Offset of baseChar: " << (char*)&b.baseChar - (char*)&b << endl;
    cout << "Offset of baseConst: " << (char*)&b.baseConst - (char*)&b << endl;
    cout << "Offset of baseStaticInt: " << (char*)&Base::baseStaticInt - (char*)&b << endl;
    cout << "Offset of baseStaticConst: " << (char*)&Base::baseStaticConst - (char*)&b << endl;

    return 0;
}

运行结果为:

Size of Base class: 32 bytes
Offset of baseShort: 8
Offset of baseInt: 12
Offset of baseChar: 16
Offset of baseConst: 24
Offset of baseStaticInt: -140725407776668
Offset of baseStaticConst: -140725409879624

可以看出编译器将变量进行了适当对齐,而静态成员变量并不位于类的内存中。

派生类类内成员的内存分布

当出现继承时,如果没有虚函数,则基类的内存地址位于派生类的起始地址;如果有虚函数,则虚函数表指针位于派生类的起始地址,其余变量按继承顺序按序分布。

例如:

#include <iostream>
using namespace std;

class Base {
public:
    short baseShort;
    int baseInt;
    char baseChar;
    const double baseConst;
    static int baseStaticInt;
    static const double baseStaticConst;
    virtual void baseFunc1() {}
    virtual void baseFunc2() {}
    Base() : baseConst(0.0) {} // 在构造函数中初始化 baseConst
};

int Base::baseStaticInt = 0; // 静态成员变量的定义
const double Base::baseStaticConst = 0.0; // 静态成员常量的定义

class Derived : public Base {
public:
    double derivedDouble;
    static int derivedStaticInt;
    static const double derivedStaticConst;
    virtual void derivedFunc1() {}
    virtual void derivedFunc2() {}
};

int Derived::derivedStaticInt = 0; // 静态成员变量的定义
const double Derived::derivedStaticConst = 0.0; // 静态成员常量的定义

int main() {
    Base b;
    Derived d;

    cout << "Size of Base class: " << sizeof(Base) << " bytes" << endl;
    cout << "Size of Derived class: " << sizeof(Derived) << " bytes" << endl;

    // 计算偏移量
    cout << "Offset of baseShort: " << (char*)&b.baseShort - (char*)&b << endl;
    cout << "Offset of baseInt: " << (char*)&b.baseInt - (char*)&b << endl;
    cout << "Offset of baseChar: " << (char*)&b.baseChar - (char*)&b << endl;
    cout << "Offset of baseConst: " << (char*)&b.baseConst - (char*)&b << endl;
    cout << "Offset of baseStaticInt: " << (char*)&Base::baseStaticInt - (char*)&b << endl;
    cout << "Offset of baseStaticConst: " << (char*)&Base::baseStaticConst - (char*)&b << endl;
    cout << "Offset of derivedDouble: " << (char*)&d.derivedDouble - (char*)&d << endl;
    cout << "Offset of derivedStaticInt: " << (char*)&Derived::derivedStaticInt - (char*)&d << endl;
    cout << "Offset of derivedStaticConst: " << (char*)&Derived::derivedStaticConst - (char*)&d << endl;

    cout << "Offset of baseShort in Derived: " << (char*)&b.baseShort - (char*)&b << endl;
    cout << "Offset of baseInt in Derived: " << (char*)&d.baseInt - (char*)&d << endl;
    cout << "Offset of baseChar in Derived: " << (char*)&d.baseChar - (char*)&d << endl;
    cout << "Offset of baseConst in Derived: " << (char*)&d.baseConst - (char*)&d << endl;
    cout << "Offset of baseStaticInt in Derived: " << (char*)&Base::baseStaticInt - (char*)&d << endl;
    cout << "Offset of baseStaticConst in Derived: " << (char*)&Base::baseStaticConst - (char*)&d << endl;

    return 0;
}

运行结果为:

Size of Base class: 32 bytes
Size of Derived class: 40 bytes
Offset of baseShort: 8
Offset of baseInt: 12
Offset of baseChar: 16
Offset of baseConst: 24
Offset of baseStaticInt: -140726083185396
Offset of baseStaticConst: -140726085287800
Offset of derivedDouble: 32
Offset of derivedStaticInt: -140726083185344
Offset of derivedStaticConst: -140726085287744
Offset of baseShort in Derived: 8
Offset of baseInt in Derived: 12
Offset of baseChar in Derived: 16
Offset of baseConst in Derived: 24
Offset of baseStaticInt in Derived: -140726083185348
Offset of baseStaticConst in Derived: -140726085287752

标签:int,double,布局,Derived,C++,Base,内存,Offset,baseConst
From: https://www.cnblogs.com/JasenChao/p/18047968

相关文章

  • C++ 把引用作为参数
    1#include<iostream>2usingnamespacestd;34//函数声明5voidswap(int&x,int&y);67intmain()8{9//局部变量声明10inta=100;11intb=200;1213cout<<"交换前,a的值:"<<a<<en......
  • C++ 从函数返回指针
    C++允许从函数返回指针,必须声明一个返回指针的函数:int*myFunction()C++不支持在函数外返回局部变量的地址,除非定义局部变量为static变量。1#include<iostream>2#include<ctime>3#include<cstdlib>4 5usingnamespacestd;6 7//要生成和返回随......
  • C++ 指针 vs 数组
    指针和数组并不是完全互换的1#include<iostream>23usingnamespacestd;4constintMAX=3;56intmain()7{8intvar[MAX]={10,100,200};910for(inti=0;i<MAX;i++)11{12*var=i;//这是正确的语法13......
  • C++类开发第五篇(继承和派生的初体验)
    inheritance在C++中,继承是一种面向对象编程的特性,允许一个类(称为子类或派生类)从另一个类(称为基类或父类)那里继承属性和行为。通过继承,子类可以获得父类的数据成员和成员函数,从而可以重用父类的代码并扩展其功能。这样可以提高代码的复用性和可维护性,同时也符合面向对象编程的封......
  • delphi 新版内存表 FDMemTable使用SQL查询(02)
    fdLocalSql可以对fdMemTable内存表进行SQL查询(可以对多个fdMemTable内存表进行联表查询哦),fdLocalSql使用SQLITE引擎,而FIREDAC驱动SQLITE,连SQLITE驱动DLL都不需要附带的。1)设置fdConnection为SQLITE,LoginPrompt设为False; 2)设置TfdLocalSQL 的Connection 3)拖一个FDMemTa......
  • C++static 存储类
    1#include<iostream>23//函数声明4voidfunc(void);56intmain()7{8intcount=10;9while(count--)10{11func();12std::cout<<",变量count为"<<count<<std::endl;13......
  • python生成Excel文件减少使用内存
    1、openpyxl模块生成2、xlsxwriter模块contant_memory=True生成TRANSLATEwithxEnglishArabicHebrewPolishBulgarianHindiPortugueseCatalanHmongDawRomanianChineseSimplifiedHungarianRussianChineseTraditionalIndonesianSlovak......
  • (持续更新)c++指针
    空指针和野指针1.空指针定义:指针变量指向内存中编号为0的空间用途:初始化指针变量注意:空指针指向的内存是不可以访问的   2.野指针   const修饰指针1.const修饰指针constint*p=&a;图中:*p=20;错误,指针指向的值不可以改p=&b;正确,指针的指向可以改 (常量......
  • faster-fifo:C++实现的python多进程通信队列 —— 强化学习ppo算法库sample-factory的C
    项目地址:https://github.com/alex-petrenko/faster-fifo需要注意,该项目给出了两种安装方法,一种是pip从pypi官网安装,一种是从GitHub上的源码安装;经过测试发现这个项目维护程度较差,因此pypi官网上的项目比较落后,因此不建议使用pypi上的安装,而是进行源码编译安装。给出源码编......
  • Linux查看服务器内存
    参考:https://blog.csdn.net/while_int/article/details/130844627freefree命令用来显示系统内存状态,包括系统物理内存、虚拟内存(swap交换分区)、共享内存和系统缓存的使用情况#-m选项是以MB为单位来展示内存使用信息free-m#-h选项则是以人类(human)可读的单位来展示free......