zoukankan      html  css  js  c++  java
  • C++对象内存分布(3)

    1.前言

    本篇文章的全部代码样例。假设是windows上编译执行。则使用的是visual studio 2013。假设是RHEL6.5平台(linux kernal: 2.6.32-431.el6.i686)上编译执行,则其gcc版本号为4.4.7,例如以下所看到的:
    [root@MiWiFi-R1CM ~]# gcc --version
    gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-4)

    2.菱形继承类的内存分布

    本篇文章主要讨论的是虚继承(virtual)下的内存分布。

    2.1.类的结构


    2.2.实现代码windows版本号

    以下的代码执行在windows 7+visual studio 2013平台上。

    分别打印类Base1对象的内存分布。和类Derive对象的内存分布。

    #include <iostream>  
    using namespace std;
    class Base 
    {
    public:
    	int _iBase;
    	char _cBase;
    public:
    	Base() : _iBase(1111), _cBase('A') 
    	{
    	}
    	virtual void func() 
    	{
    		cout << "Base::func()" << endl;
    	}
    	virtual void baseFunc() 
    	{
    		cout << "Base::baseFunc()" << endl;
    	}
    };
    
    class Base1 : public virtual Base 
    {
    public:
    	int _iBase1;
    	char _cBase1;
    public:
    	Base1() : _iBase1(2222), _cBase1('B')
    	{
    	}
    	virtual void func()
    	{
    		cout << "Base1::func()" << endl;
    	}
    	virtual void func1()
    	{
    		cout << "Base1::func1()" << endl;
    	}
    	virtual void baseFunc1()
    	{
    		cout << "Base1::baseFunc1()" << endl;
    	}
    };
    
    class Base2 : public virtual Base
    {
    public:
    	int _iBase2;
    	char _cBase2;
    public:
    	Base2() : _iBase2(3333), _cBase2('C') 
    	{
    	}
    	virtual void func()
    	{
    		cout << "Base2::func()" << endl;
    	}
    	virtual void func2()
    	{
    		cout << "Base2::func2()" << endl;
    	}
    	virtual void baseFunc2()
    	{
    		cout << "Base2::baseFunc2()" << endl;
    	}
    };
    
    class Derive : public virtual Base1, public virtual Base2
    {
    public:
    	int _iDerive;
    	char _cDerive;
    public:
    	Derive() : _iDerive(4444), _cDerive('D')
    	{
    	}
    	virtual void func()
    	{
    		cout << "Derive::func()" << endl;
    	}
    	virtual void func1()
    	{
    		cout << "Derive::func1()" << endl;
    	}
    	virtual void func2()
    	{
    		cout << "Derive::func2()" << endl;
    	}
    	virtual void deriveFunc()
    	{
    		cout << "Derive::deriveFunc()" << endl;
    	}
    };
    
    typedef void(*Fun)();
    
    int main() {
    	int **pVtab = NULL;
    	Fun pFun = NULL;
    
    	Base1 bb1;
    
    	cout << "sizeof(Base)" << sizeof(Base) << endl;
    	cout << "sizeof(Base1)" << sizeof(Base1) << endl;
    
    	//Base1 layout
    	pVtab = (int**)&bb1;
    	cout << "[0] Base1::_vptr->" << "  addr:" << &pVtab[0] << endl;
    	pFun = (Fun)pVtab[0][0];
    	cout << "    [0]";
    	pFun(); //Base1::func1()
    	pFun = (Fun)pVtab[0][1];
    	cout << "    [1]";
    	pFun(); //Base1::baseFunc1()
    	cout << "    [2]";
    	cout << pVtab[0][2] << endl;
    
    	cout << "[1] Base1::_vbptr->" << "  addr:" << &pVtab[1] << endl;
    	cout << "    [0]";
    	cout << pVtab[1][0] << endl;
    	cout << "    [1]offset->";
    	cout << pVtab[1][1] << endl;
    	cout << "    [2]";
    	cout << pVtab[1][2] << endl;
    
    	cout << "[2] Base1:_iBase1 -> ";
    	cout << (int)pVtab[2] << endl; //Base1:_iBase1
    
    	cout << "[3] Base1:_cBase1 -> ";
    	cout << (char)(int)pVtab[3] << endl; //Base1:_cBase1
    
    	cout << "[4] unknown ";
    	cout << (int)pVtab[4] << endl;
    
    	cout << "[5] Base::_vfptr->" << "  addr:" << &pVtab[4] << endl;
    	cout << "    [0]";
    	pFun = (Fun)pVtab[5][0];
    	pFun();
    	cout << "    [1]";
    	pFun = (Fun)pVtab[5][1];
    	pFun();
    	cout << "    [2]";
    	cout << (int)pVtab[5][2] << endl;
    
    	cout << "[6] Base:_iBase -> ";
    	cout << (int)pVtab[6] << endl; //Base:_iBase
    
    	cout << "[7] Base:_cBase -> ";
    	cout << (char)(int)pVtab[7] << endl; //Base:_cBase
    
    	cout << endl;
    	cout << "###########################" << endl;
    	cout << endl;
    
    	//Derive layout
    	// sub Derive vtbl layout
    	Derive d;
    	cout << "sizeof(Derive)" << sizeof(Derive) << endl;
    
    	pVtab = (int**)&d;
    	cout << "[0] Derive::_vfptr->" << "  addr:" << &pVtab[0] << endl;
    	cout << "     [0] ";
    	pFun = (Fun)pVtab[0][0];
    	pFun(); //Derive::func1();
    	cout << "     [1] ";
    	cout << pVtab[0][1] << endl;
    
    	cout << "[1] Derive::_vbptr->" << "  addr:" << &pVtab[1] << endl;
    	cout << "     [0] ";
    	cout << pVtab[1][0] << endl;
    	cout << "     [1]offset-> ";
    	cout << pVtab[1][1] << endl;
    	cout << "     [2] ";
    	cout << pVtab[1][2] << endl;
    	cout << "     [3] ";
    	cout << pVtab[1][3] << endl;
    	cout << "     [4] ";
    	cout << pVtab[1][4] << endl;
    
    	cout << "[2] Derive::_iDerive -> ";
    	cout << (int)pVtab[2] << endl; //Derive:_iDerive
    
    	cout << "[3] Derive::_cDerive -> ";
    	cout << (char)(int)pVtab[3] << endl; //Derive::_cDerive
    
    	cout << "[4] unknown-> " << (int)pVtab[4] << endl;
    
    	// sub Base vtbl layout
    	cout << "[5] Base::_vfptr->" << "  addr:" << &pVtab[5] << endl;
    	cout << "     [0] ";
    	pFun = (Fun)pVtab[5][0];
    	pFun();
    	pFun = (Fun)pVtab[5][1];
    	cout << "     [1] ";
    	pFun();
    	cout << "     [2] ";
    	cout << pVtab[5][2] << endl;
    
    	cout << "[6] Base::_iBase -> ";
    	cout << (int)pVtab[6] << endl;
    
    	cout << "[7] Base::_cBase -> ";
    	cout << (char)(int)pVtab[7] << endl;
    
    	cout << "[8] unknown-> ";
    	cout << (int)pVtab[8] << endl;
    
    	// sub Base1 vtbl layout
    	cout << "[9] Base1::_vfptr->" << "  addr:" << &pVtab[9] << endl;
    	cout << "     [0] ";
    	cout << pVtab[9][0] << endl;
    	pFun = (Fun)pVtab[9][1];
    	cout << "     [1] ";
    	pFun();
    	pFun = (Fun)pVtab[9][2];
    	cout << "     [2] ";
    	cout << (int)pFun << endl;
    	pFun = (Fun)pVtab[9][3];
    	cout << "     [3] ";
    	cout << (int)pFun << endl;
    
    	cout << "[10] unknown-> ";
    	cout << (int)pVtab[10] << endl;
    
    	cout << "[11] Base1::_iBase1 -> ";
    	cout << (int)pVtab[11] << endl;
    
    	cout << "[12] Base1::_cBase1 -> ";
    	cout << (char)(int)pVtab[12] << endl;
    
    	cout << "[13] unknown-> ";
    	cout << (int)pVtab[13] << endl;
    
    	// sub Base2 vtbl layout
    	cout << "[14] Base2::_vfptr->" << "  addr:" << &pVtab[14] << endl;
    	cout << "     [0] ";
    	cout << pVtab[14][0] << endl;
    	pFun = (Fun)pVtab[14][1];
    	cout << "     [1] ";
    	pFun();
    	cout << "     [2] ";
    	cout << pVtab[14][2] << endl;
    	cout << "     [3] ";
    	cout << pVtab[14][3] << endl;
    
    	cout << "[15] unknown-> ";
    	cout << (int)pVtab[15] << endl;
    
    	cout << "[16] Base2::_iBase2 -> ";
    	cout << (int)pVtab[16] << endl;
    
    	cout << "[17] Base2::_cBase2 -> ";
    	cout << (char)(int)pVtab[17] << endl;
    
    	return 0;
    }

    Base1对象的内存分布为:


    Derive对象的内存分布为:


    2.3.实现代码linux版本号

    以下代码中,对于这4个类的定义,与前面的windows代码中对类的定义是全然一样的,所以这里省略掉了。仅仅列出用于输出内存分布的代码:

    int main() 
    {
    	int **pVtab = NULL;
    	Fun pFun = NULL;
    
    	Base1 bb1;
    
    	cout << "sizeof(Base)" << sizeof(Base) << endl;
    	cout << "sizeof(Base1)" << sizeof(Base1) << endl;
    
    	//Base1 layout
    	pVtab = (int**)&bb1;
    	cout << "[0] Base1::_vptr->" << "  addr:" << &pVtab[0] << endl;
    	pFun = (Fun)pVtab[0][0];
    	cout << "    [0]";
    	pFun(); //Base1::func1()
    	pFun = (Fun)pVtab[0][1];
    	cout << "    [1]";
    	pFun(); //Base1::baseFunc1()
    	pFun = (Fun)pVtab[0][2];
    	cout << "    [2]";
    	pFun();
    	cout << "    [3]";
    	cout << pVtab[0][3];
    
    	cout << "[1] Base1:_iBase1 -> ";
    	cout << (int)pVtab[1] << endl;  //Base1:_iBase1
    
    	cout << "[2] Base1:_cBase1 -> ";
    	cout << (char)(int)pVtab[2] << endl;  //Base1:_cBase1
    
    	// Base layout
    	cout << "[3] Base::_vptr->" << "  addr:" << &pVtab[3] << endl;
    	pFun = (Fun)pVtab[3][0];
    	cout << "    [0]";
    	pFun(); //Base1::func()
    	pFun = (Fun)pVtab[3][1];
    	cout << "    [1]";
    	pFun(); //Base::baseFunc()
    	cout << "    [2]";
    	cout << pVtab[3][2] << endl;
    
    	cout << "[4] Base:_iBase -> ";
    	cout << (int)pVtab[4] << endl; //Base:_iBase
    	cout << "[5] Base:_cBase -> ";
    	cout << (char)(int)pVtab[5] << endl; //Base:_cBase
    
    	cout << "[6] " << (int)pVtab[6] << "  addr:" << &pVtab[6] << endl; //dirty data
    
    	cout << endl;
    	cout << "###########################" << endl;
    	cout << endl;
    
    	// Derive layout
    	// sub Derive vtbl layout
    	Derive d;
    	cout << "sizeof(Derive)" << sizeof(Derive) << endl;
    
    	pVtab = (int**)&d;
    	cout << "[0] Derive::_vfptr->" << "  addr:" << &pVtab[0] << endl;
    	cout << "     [0] ";
    	pFun(); //Derive::func1();
    	pFun = (Fun)pVtab[0][1];
    	cout << "     [1] ";
    	pFun(); //Base1::baseFunc1();
    	pFun = (Fun)pVtab[0][2];
    	cout << "     [2] ";
    	pFun(); //Derive::deriveFunc();
    	pFun = (Fun)pVtab[0][3];
    	cout << "     [3] ";
    	pFun();
    	cout << "     [4] ";
    	cout << pVtab[0][4] << endl;
    
    	cout << "[1] Derive:_iDerive -> ";
    	cout << (int)pVtab[1] << endl; //Derive:_iDerive
    
    	cout << "[2] Derive:_cDerive -> ";
    	cout << (char)(int)pVtab[2] << endl; //Derive:_cDerive
    
    	// sub Base1 vtbl layout
    	cout << "[3] Base1::_vptr->" << "  addr:" << &pVtab[3] << endl;
    	pFun = (Fun)pVtab[3][0];
    	cout << "     [0] ";
    	pFun();
    	pFun = (Fun)pVtab[3][1];
    	cout << "     [1] ";
    	pFun();
    	pFun = (Fun)pVtab[3][2];
    	cout << "     [2] ";
    	pFun();
    	cout << "     [3] ";
    	cout << pVtab[3][3] << endl;
    
    	cout << "[4] Base1::_iBase1 -> ";
    	cout << (int)pVtab[4] << endl;
    
    	cout << "[5] Base1::_cBase1 -> ";
    	cout << (char)(int)pVtab[5] << endl;
    
    	// sub Base vtbl layout
    	cout << "[6] Base::_vptr->" << "  addr:" << &pVtab[6] << endl;
    	pFun = (Fun)pVtab[6][0];
    	cout << "     [0] ";
    	pFun();
    	pFun = (Fun)pVtab[6][1];
    	cout << "     [1] ";
    	pFun();
    	pFun = (Fun)pVtab[6][2];
    	cout << "     [2] ";
    	cout << (int)pFun << endl;
    
    	cout << "[7] Base::_iBase -> ";
    	cout << (int)pVtab[7] << endl;
    
    	cout << "[8] Base::_cBase -> ";
    	cout << (char)(int)pVtab[8] << endl;
    
    	// sub Base2 vtbl layout
    	cout << "[9] Base2::_vptr->" << "  addr:" << &pVtab[9] << endl;
    	pFun = (Fun)pVtab[9][0];
    	cout << "     [0] ";
    	pFun();
    	pFun = (Fun)pVtab[9][1];
    	cout << "     [1] ";
    	pFun();
    	pFun = (Fun)pVtab[9][2];
    	cout << "     [2] ";
    	pFun();
    	cout << "     [3] ";
    	cout << pVtab[9][3] << endl;
    
    	cout << "[10] Base2::_iBase2 -> ";
    	cout << (int)pVtab[10] << endl;
    
    	cout << "[11] Base2::_cBase2 -> ";
    	cout << (char)(int)pVtab[11] << endl;
    
    	return 0;
    }
    Base1对象的内存分布为:


    Derive对象的内存分布为:

    2.4.Base1类的内存分布对照

                   Windows 7 + Visual studio 2013                                      Linux RHEL6.5 + gcc 4.4.7


    2.5.Derive类的内存分布对照

                         Windows 7 + Visual studio 2013                                      Linux RHEL6.5 + gcc 4.4.7


    2.6.Derive类在虚继承与非虚继承中的内存对照

    在前面的章节(2.5)中,已经列出了Derive在虚继承(virtual)的情况下,在windows以及linux平台下的具体内存分布。
    在前一篇文章中,我们获得了非虚继承(non virtual)的情况下,Derive类的内存分布。

    这里将它与本篇文章中获得的虚继承的分布。进行一个对照。


    下图是windows平台下。非虚继承与虚继承对类的内存分布的影响对照。

                        非虚继承(non virtual)                                                            虚继承(virtual)


    下图是linux平台下。非虚继承与虚继承对类的内存分布的影响对照。


                       非虚继承(non virtual)                                                            虚继承(virtual)


  • 相关阅读:
    hdu4417 Super Mario
    bzoj3110 zjoi2013 K大数查询
    转:如何理解c和c ++的复杂类型声明
    UVa 489 刽子手游戏
    bzoj1006 神奇的国度
    bzoj2764 基因补全
    bzoj2338 数矩形
    bzoj3720 gty的妹子树
    Struts2(一)入门及工作原理
    输入人民币/美元后自动判断,输出转换后相对应的值
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/6855163.html
Copyright © 2011-2022 走看看