C++ 类的内存布局

基类类内成员的内存分布

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

  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
posted on 2024-03-01 21:14  未连接到互联网  阅读(27)  评论(0编辑  收藏  举报