当前位置导航:炫浪网>>网络学院>>编程开发>>C++教程>>C++进阶与实例

C++对象布局及多态实现探索之内存布局

    前言

  本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了c++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等。

  写这篇文章源于我在论坛上看到的一个贴子。有人问vc使用了哪种方式来实现虚继承。当时我写了一点代码想验证一下,结果发现情况比我想象的要复杂。所以我就干脆认真把相关的问题都过了一遍,并记录成本文。

  我对于c++对象模型的知识主要来自于lippman的书《inside the c++ object model》,中译版为候捷翻的《深度探索c++对象模型》,中英版我都看过,不过我还是推荐中译版,因为中译版的确翻得不错,而且候捷加入了很多的图,并修正了原版中的一些错误。

  我所使用的编译器是vc7.1,文中的代码我都在vc7.1上验证通过。如果在其他的编译器下运行需要作相应的调整,即使是vc7.0和vc6也是如此。不同编译器产生的汇编代码也不一样,如果你在不同编译器上编译文中的代码生成出的汇编代码和我所列出的不同,也不足为奇。如果你想在其他的编译器上验证这些代码请自行做相应的改动。

  另外我发现vc7.1在实现虚继承时所用的方法和lippman在书中提到的微软所用的方法不同,不过那时还没有vc7.1。有趣的是,lippman在写那本书时,是在迪斯尼工作,应该是做和三维影片的渲染软件相关的事。而现在他已经到了微软,相信应该是主导vc7.1编译器的设计工作。

  在后文中可以看到列出的很多汇编代码,有些明显效率很低。这可能是因为我没有打开编译器的优化开关。打开优化开关,设置不同的优化选项后,编译器可能产生出高效得多的汇编代码。有兴趣的朋友可以自行试试,并和文中列出的汇编代码做一下比较。

  为了便于分析和观察对象的内存布局,我把代码生成时的结构成员对齐选项设置为1字节,默认为8字节。如果你在自己的工程下编译文中的代码,请做同样的设置。因为我写了一些函数打印对象中的布局信息,如果对象选项不是1字节,运行这些代码会出现指针异常错误。

  普通类对象的内存布局

  首先我们从普通类对象的内存布局开始。c000为一个空类,定义如下:

    struct c000
    {};
  运行如下代码打印它的大小及对象中的内容。

    print_size_detail(c000)

  结果为:

    the size of c000 is 1

    the detail of c000 is cc

  可以看到它的大小为1字节,这是一个占位符。我们可以看到它的值是0xcc。在debug模式下,这表示是由编译器插入的调试代码所初始化的内存。在release模式下可能是个随机值,我测试时值为0x00。

  定义两个类,c010和c011如下:

 struct c010
{
 c010() : c_(0x01) {}
 void foo() { c_ = 0x02; }
 char c_;
};
struct c011
{
 c011() : c1_(0x02), c2_(0x03) {}
 char c1_;
 char c2_;
};

 

共4页 首页 上一页 1 2 3 4 下一页 尾页 跳转到
相关内容
赞助商链接