美文网首页
C++中对象的内存布局(一)

C++中对象的内存布局(一)

作者: 星星326 | 来源:发表于2023-10-30 21:58 被阅读0次

在上篇文章《戳我》中,简单说了继承的三种分类:单继承、多重继承、重复继承。

一般的如果没有虚函数,那对象的内存布局就如我们看到的一样,定义了几个变量根据字节对齐就能算出其在内存中所占字节大小。但是有了虚函数,就不同了,因为有了虚函数就意味着存在虚函数指针,那指针我们知道是占四个字节(32位)的,所以从本篇文章开始来分析存在虚函数时对象的内存布局是怎么样的?(版本是Visual Studio2012)

对于单继承:


image.png

写出以下代码:

class Father
{
public:
    Father(int data1):fa(data1){}
    virtual void f(){cout<<"Father::f()"<<" ";}
    virtual void ff(){cout<<"Father::ff()"<<" ";}
    virtual void fff(){cout<<"Father::fff()"<<" ";}
protected:
    int fa;
};
 
class Son:public Father
{
public:
    Son(int data):sa(data),Father(data){}
    virtual void f(){cout<<"Son::f()"<<" ";}
    virtual void ss(){cout<<"Son::ss()"<<" ";}
    virtual void sss(){cout<<"Son::sss()"<<" ";}
protected:
    int sa;
};
class Grandson:public Son
{
public:
    Grandson(int data):ga(data),Son(data){}
    virtual void f(){cout<<"Grandson::f()"<<" ";}
    virtual void ss(){cout<<"Grandson::ss()"<<" ";}
    virtual void ggg(){cout<<"Grandson::ggg()"<<" ";}
protected:
    int ga;
};
typedef void (*Function)(void);//函数指针
int main()
{
    //main函数主要进行打印
    Grandson *pgs=new Grandson(12);
    Function pFun=NULL;//定义一个函数指针
 
    cout<<"[0]   _vfptr"<<endl;
    for(int i=0;i<6;++i)
    {
        pFun=((Function*)(long**)(*(long*)(pgs)))[i];
        cout<<"   "<<"["<<i<<"]"<<" ";
        pFun();
        cout<<((long**)(*(long*)pgs))[i]<<endl;
    }
 
    cout<<"[1] "<<((long*)pgs)[1]<<endl;
    cout<<"[2] "<<((long*)pgs)[2]<<endl;
    cout<<"[3] "<<((long*)pgs)[3]<<endl;
    
    delete pgs;
    return 0;
}
注:
(long*)(pgs):将pgs强转成long*
(*(long*)(pgs)):解引用,虚函数表的地址
(long**)(*(long*)(pgs)):虚函数表的地址强转成二级指针

查看Grandson类生成对象的内存布局:(点击【项目】-》【属性】-》【C/C++】-》【命令行】-》在其它选项处写上

【/d1 reportSingleClassLayoutGrandson】-》点击【确定】就好了 )

image.png

可以看出:

1、子类继承了父类的成员变量,成员函数不占空间。

2、有虚函数时出现了一个vfptr指针,并把该指针放在了内存的开始处(相对对象偏移为0)。

3、同名的函数在虚表中被覆盖。

4、同时也看到了有一张虚表的存在,虚表中从0号下标开始就存放的是虚函数,有一个问题就是从虚表中也能看出有RTTI信息(&Grandson_meta)和vfptr相对于类型的偏移信息(0),但它不在0号下标锁对应的位置,那它在哪?怎么打印出来?看到的宝宝希望能帮我解答。

将上面程序进行打印及调试,可以看到:

image.png

现在,我们来画出单继承下Grandson类的内存布局:

image.png

https://blog.csdn.net/zhuoya_/article/details/80032784

相关文章

  • NSObject 底层本质

    一、OC 转 C/C++ 二、NSObject 对象内存布局 三、NSObject 内存大小 四、OC 对象内存布...

  • iOS中OC对象的本质

    一个OC对象在内存中如何布局?以及一个NSObject对象占用多少内存? 我们知道OC的底层语言是c/c++我们平...

  • 深度探索C++对象模型(内存分布, 虚函数表)

    虽然C++面向对象很容易上手, 但是一直对C++对象的底层实现不知甚解, 得益于vs自带cl命令可以查看内存布局,...

  • C++ 对象内存布局

    虚函数, 虚基类 同时存在的时候, 对象内存布局的影响。 转自对象内存布局 (16) - CSDN博客 虚基类指针...

  • C++ 对象内存布局

    可能会对 C++ 对象的内存布局产生影响的因素: 对象的数据成员变量 对象的一般成员函数 对象的虚成员函数 对象继...

  • 对象的内存布局

    对象的内存布局 在Hotspot虚拟机中,对象在内存中的布局可以分为三块区域: 对象头(Header)、实例数据(...

  • JAVA运行时—内存分配情况

    对象的内存布局 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据...

  • C++之内存布局

    在C++之内存管理一文中,我们已经了解到C++的内存管理,这里介绍C++的典型内存布局结构。 1、总体来说,C/C...

  • 【第三篇】深入学习Java虚拟机之对象的内存布局及访问定位

    一、对象的内存布局 在HotSpot虚拟机中,对象在内存中存储布局可以分为3块区域:对象头、实例数据、和对齐填充 ...

  • Java对象的内存布局以及访问方式

    对象的内存布局 在HotSpot虚拟机中,对象的内存中的布局可以分为3块区域:对象头,实例数据和对齐填充。 对象头...

网友评论

      本文标题:C++中对象的内存布局(一)

      本文链接:https://www.haomeiwen.com/subject/uztiidtx.html