美文网首页
对象内存布局

对象内存布局

作者: cp3_1dbc | 来源:发表于2018-04-03 00:18 被阅读0次

    类的内存布局

    看下面的程序中,输出的结果会是what?

    class Base
    {
    public:
        //Base();
        ~Base();
        virtual void f() {} 
        static Base origin;
        int a, b, c;
    };
    
    int main(int argc, char const *argv[])
    {
        printf("%p\n", &Base::a);
        printf("%p\n", &Base::b);
        printf("%p\n", &Base::c);
    
        Base* base = new Base;
        printf("%p\n", &base->a);
        printf("%p\n", &base->b);
        printf("%p\n", &base->c);
    
        return 0;
    }
    

    运行结果

    0x8
    0xc
    0x10
    0x1f4a038
    0x1f4a03c
    0x1f4a040
    

    分析

    Inside C++ Object Model第三章中有这样的介绍:

    • 取一个类的非静态数据成员的地址,将会得到它在class中的offset。
    • 取一个对象的非静态数据成员的地址,将会得到它在内存中的真正地址。

    &Base::a = 0x8,在64bit系统下正好是一个指针的大小,Base包含虚函数,可以vptr是在类的起始位置。
    虚拟继承

    虚基类的两种实现方式

    1. Microsoft编译器引入所谓的virtual base class table,每一个类如果有一个或多个虚基类,就会有编译器安插一个指针,指向虚基类表,而真正的虚基类指针放在表格中。


      clipboard.png
    2. 第二种方法是在virtual function table中放置virtual base class的offset


      clipboard1.png

    虚函数表到底在哪

    因为在程序里每个类只需要一个vtbl拷贝,所以编译器肯定会遇到一个棘手的问题:
    把它放在哪里。大多数程序和程序库由多个object(目标)文件连接而成,但是每个object
    文件之间是独立的。哪个object文件应该包含给定类的vtbl呢?你可能会认为放在包含
    main函数的object文件里,但是程序库没有main,而且无论如何包含main的源文件不会
    涉及很多需要vtbl的类。编译器如何知道它们被要求建立那一个vtbl呢?

    1. 必须采取一种不同的方法,编译器厂商为此分成两个阵营。对于提供集成开发环境(包含编译程序和连接程序)的厂商,一种干脆的方法是为每一个可能需要vtbl的object文件生成一个vtbl拷贝。连接程序然后去除重复的拷贝,在最后的可执行文件或程序库里就为每个vtbl保留一个实例。
    2. 更普通的设计方法是采用启发式算法来决定哪一个object文件应该包含类的vtbl。通常启发式算法是这样的:要在一个object文件中生成一个类的vtbl,要求该object文件包含该类的第一个非内联、非纯虚拟函数(non-inline non-pure virual function)定义(也就是类的实现体)。因此上述C1类的vtbl将被放置到包含C1::~C1定义的object文件里(不是内联的函数),C2类的vtbl被放置到包含C1::~C2定义的object文件里(不是内联函数)。

    实际当中,这种启发式算法效果很好。但是如果你过分喜欢声明虚函数为内联函数(参见Effective C++条款33) ,如果在类中的所有虚函数都内声明为内联函数,启发式算法就会失败,大多数基于启发式算法的编译器会在每个使用它的object 文件中生成一个类的vtbl。在大型系统里,这会导致程序包含同一个类的成百上千个vtbl拷贝!大多数遵循这种启发式算法的编译器会给你一些方法来人工控制vtbl的生成,但是一种更好的解决此问题的方法是避免把虚函数声明为内联函数。下面我们将看到,有一些原因导致现在的编译器一般总是忽略虚函数的的inline指令。

    相关文章

      网友评论

          本文标题:对象内存布局

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