zoukankan      html  css  js  c++  java
  • C++对象的内存布局以及虚函数表和虚基表

    C++对象的内存布局以及虚函数表和虚基表

    本文为整理文章,

    参考:

    http://blog.csdn.net/haoel/article/details/3081328

    http://blog.csdn.net/angelxf/article/details/7746034

     

    整理的也不到位,还有很多不理解,先记下来。

     

    遇到了一个面试题,是求对象所占空间的大小了。于是想了解一下C++中对象内存的布局。

    先来一些结论,以便应付面试:

    l  空类、单一继承的空类、多重继承的空类所占空间大小为:1(字节,下同);

    l  一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间的;

    l  因此一个对象的大小≥所有非静态成员大小的总和;

    l  当类中声明了虚函数(不管是1个还是多个),那么在实例化对象时,编译器会自动在对象里安插一个指针vPtr指向虚函数表VTable

    l  虚承继的情况:由于涉及到虚函数表和虚基表,会同时增加一个(多重虚继承下对应多个)vfPtr指针指向虚函数表vfTable和一个vbPtr指针指向虚基表vbTable,这两者所占的空间大小为:8(或8乘以多继承时父类的个数);

    l  在考虑以上内容所占空间的大小时,还要注意编译器下的“补齐”padding的影响,即编译器会插入多余的字节补齐;

    l  类对象的大小=各非静态数据成员(包括父类的非静态数据成员但都不包括所有的成员函数)的总和+ vfptr指针(多继承下可能不止一个)+vbptr指针(多继承下可能不止一个)+编译器额外增加的字节

     

    接下来说说虚函数表和虚基表

    C++多态的实现和Java类似,都是利用虚函数表(Java叫方法表),不同的是,Java中,不用virtual修饰,函数自带virtual属性(指的是那些非静态函数)。之前的文章《从JVM角度看Java多态》中,也简单分析了Java多态的实现机制。C++Java是类似的。下面我们直接分析吧。

    对于单继承

    Child类重写了Parentf()GrandChild类重写了Child类的f()g_child();

     

    GrandChild对象的内存布局为:


     

    可以看到:

    l  虚函数表在最前面的位置。

    l  成员变量根据其继承和声明顺序依次放在后面。

    l  在单一的继承中,被overwrite的虚函数在虚函数表中得到了更新。

    对于多继承


    Derive对象的内存布局


    可以看到:

    l  每个父类都有自己的虚表。

    l  子类的成员函数被放到了第一个父类的表中

    l  内存布局中,其父类布局依次按声明顺序排列。

    l  每个父类的虚表中的f()函数都被overwrite成了子类的f()这样做就是为了解决不同的父类类型的指针指向同一个子类实例,而能够调用到实际的函数

    对于菱形继承问题


    D对象的内存布局


    可以看到

    我们可以看见,最顶端的父类B其成员变量存在于B1B2中,并被D给继承下去了。而在D中,其有B1B2的实例,于是B的成员在D的实例中存在两份,一份是B1继承而来的,另一份是B2继承而来的。所以,容易产生二义性。

     

    对于虚继承


    对于这种问题,VS中和G++采用不同的方式

    VS D的内存布局是这样的:

     



    还不是很明白,总之就是公共基类B会放到最后,而且VS中会有虚基表的概念,vbptr就是指向虚基表的指针

     

    对于g++则没有虚基表的概念。

     

    先记下来,以后再修改

  • 相关阅读:
    Linux常用命令-centos
    USACO 2006 Open, Problem. The Country Fair 动态规划
    USACO 2007 March Contest, Silver Problem 1. Cow Traffic
    USACO 2007 December Contest, Silver Problem 2. Building Roads Kruskal最小生成树算法
    USACO 2015 February Contest, Silver Problem 3. Superbull Prim最小生成树算法
    LG-P2804 神秘数字/LG-P1196 火柴排队 归并排序, 逆序对
    数据结构 并查集
    浴谷国庆集训 对拍
    1999 NOIP 回文数
    2010 NOIP 普及组 第3题 导弹拦截
  • 原文地址:https://www.cnblogs.com/qingergege/p/7610898.html
Copyright © 2011-2022 走看看