美文网首页
对象内存布局

对象内存布局

作者: 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指令。

相关文章

  • java 内存布局

    Java 内存的布局主要是统计Java对象占用内存的大小。 Java对象的内存布局:对象头(Header)、实例数...

  • 一文详解 NSObject 对象的内存布局

    一文详解 NSObject 对象的内存布局一文详解 NSObject 对象的内存布局

  • Java对象

    Java对象的内存布局?对象的访问?new对象的过程? 一、Java对象的内存布局 对象的创建过程就是在堆上分配实...

  • JVM(七)内存与垃圾回收|对象的实例化内存布局与访问定位+直接

    本文主要讲对象相关(对象实例化、内存布局、访问定位)和直接内存相关的内容。 目录 1 对象的实例化内存布局与访问定...

  • iOS 内存管理

    一.内存布局以及结构 1.1内存布局 1.2内存管理方案 内存管理方案有3种:TaggedPointer (小对象...

  • 对象的内存布局

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

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

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

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

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

  • 对象内存布局

    类的内存布局 看下面的程序中,输出的结果会是what? 运行结果 分析 Inside C++ Object Mod...

  • 对象内存布局

    初始化一个对象 对象没初始化之前,调试窗口执行x/4gx objc2输出如下: 可见栈地址里面放的还是空的执行代码...

网友评论

      本文标题:对象内存布局

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