c++类实例对象内存布局

本文详细探讨了C++类实例对象的内存布局,包括单一简单类、带有虚函数的类、无虚函数的多继承、有虚函数的多继承、菱形继承和虚继承等场景。通过编译器的/d1 reportAllClassLayout选项,分析了各类型类的成员变量位置、虚函数表指针(vfptr)、虚函数表(vftable)以及虚继承的实现方式,揭示了C++中多态和内存管理的底层机制。
摘要由CSDN通过智能技术生成

首先为cpp文件添加额外的命令行选项 /d1 reportAllClassLayout
下面对几种情况分别讨论

单一简单类

class father
{
public:
    father(){};
    ~father(){};
public:
    void doSomething(){};
    static void sDoSomething(){};
private:
    char a;
    int b;
    static int c;
};

对他进行编译,我们可以在控制台看到

1> class father size(8):
1> + - - -
1> 0 | a
1>    | < alignment member >(size=3)
1> 4 | b
1> + - - -

开头的0,4为类内偏移。我们可以看到静态变量、函数和静态函数都不占类实例对象的内存空间。且中间有一段空白区域因内存对齐而空出来。

带有虚函数的单一类

将上面的代码简化并添加虚函数

class father
{
public:
    father(){};
    virtual ~father(){};
private:
    char a;
    int b;
public:
    virtual void doSomething(){};
};

编译结果如下

1> class father size(12):
1> + - - -
1> 0 | {vfptr}
1> 4 | a
1>    | < alignment member > (size=3)
1> 8 |  b
1> + - - -
1>
1> father::$vftable@:
1>    | &father_meta
1>    | 0
1> 0 | &father::{dtor}
1> 1 | &father::doSomething

我们可以看到跟没有虚函数相比,类的开头多了一个{vfptr},这个就是虚函数表指针,在32位下占用4字节。
继续往下看,在&father_meta下方的0表示这个虚函数表指针在类内的偏移,不过在vs2013中查看内存并没有在虚函数表的开头看到这个偏移量所占的内存。
虚函数表的开头数字则只是表示序号而不是偏移。

无虚函数的多继承

class father
{
private:
    char a;
    int b;
public:
    void doSomething(){};
};
class mother
{
private:
    char a;
    int b;
public:
    void doSomething(){};
};
class son :public father,public mother
{
public:
    char a;
    int b;
public:
    void doSomething(){};
};

编译结果如下,只把son类结构贴出来

1> class son size(24):
1>  + - - -
1>    | + - - - (base class father)
1> 0 | | a
1>    | | < alignment member > (size=3)
1> 4 | | b
1>    | + - - -
1>    | + - - - (base class mother)
1> 8 | | a
1>    | | < alignment member > (size=3)
1> 12  | | b
1>    | + - - -
1> 16  | a
1>    | < alignment member > (size=3)
1> 20  | b
1>  + - - -

通过观察发现无虚函数的正常继承,在内存中按继承的从左往右顺序连续排列,最后才是派生类。

有虚函数的多继承

class father
{
private:
    char a;
    int b;
public:
    virtual void doSomething(){};
};
class mother
{
private:
    char a;
    int b;
public:
    virtual void doSomething(){};
};
class son :public father,public mother
{
private:
    char a;
    int b;
public:
    virtual void doSomething(){};
    virtual void sonDoHimself(){};
};

编译结果如下

1>  class son   size(32):
1>      +---
1>      | +--- (base class father)
1>   0  | | {
  vfptr}
1>   4  | | a
1>      | | <alignment member> (size=3)
1>   8  | | b
1>      | +---
1>      | +--- (base class mother)
1>  12  | | {
  vfptr}
1>  16  | | a
1>      | | <alignment member> (
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值