观察这道题目主要有两点需要考虑。第一,当类里面存在虚函数时,这个类所占的内存就会比没有虚函数时候大一点,大的位置是在类的成员变量前面会多出一个指针(vptr),它指向虚指针表(vtbl),虚指针表里面的每一个指针再指向对应的虚函数。从而实现动态绑定;第二,在C语言介绍struct时,就说过一点,大多数计算机,数据项要求从某个数量字节的倍数开始存放,如short从偶数地址开始,int则被对齐在4字节边界。为了满足内存对齐,在比较小的成员后面会加入补位。在用不同的操作系统和编译器时也发现了,sizeof的结果有所不同,所以这道题目并没有正确的答案,说明所使用的操作系统和某种编译器下的情形就可以了。首先画出对象模型图示意图:
在VC6.0环境下调试结果:
所用台式机是32位系统,指针大小为4byte,而64位系统是8byte。
这是Fruit类的内存占用情况:
总共占用32byte,占用内存首地址0x0012FF28~0x0012FF44。其中首地址存放的是在Fruit类中所调用的虚函数地址。这是因为process动态绑定到Fruit类型的对象上。在VC6.0环境下,为fruit类多分出了3*(4byte)内存空间。
这是Apple类的内存占用情况:
总共占用40byte,占用内存首地址0x0012FF00~0x0012FF24。其中首地址存放的是在Apple类中所调用的虚函数地址。这是因为程序运行到子类处,所继承父类的虚函数动态绑定到子类(也就是自己)上。在VC6.0环境下,为apple类所继承的父类多分出了内存空间,编译器没有为自身在多分内存空间。
下面我在eclipse CDT上做的测试,编译器是LinuxGCC:
总共占用24byte,占用内存首地址0x0022FF18~0x0022ff2F。其中首地址存放的是在Fruit类中所调用的虚函数地址。这是因为process动态绑定到Fruit类型的对象上。在gcc下,为fruit类多分出了1*(4byte)内存空间。
同样编译器分配的内存首地址是Fruit类中动态绑定的虚函数process的地址COA54000,编译器为Fruit类分配的地址空间为0x0022FF18~0x0022ff2F。
总共占用32byte,占用内存首地址0x0022FEF8~0x0022FF17。其中首地址存放的是在Fruit类中所调用的虚函数地址。这是因为process动态绑定到Fruit类型的对象上。在gcc下,同样在所分配内存末尾出多分配1byte。
同样编译器分配的内存首地址是Apple类继承自Fruit类中动态绑定的虚函数process的地址BOA54000,编译器为Fruit类分配的地址空间为0x0022FEF8~0x0022FF17。
网友评论