c++类的内存结构

额,今日需要回家了,暂停更新博文一周。以下是之前自己测试过关于类的内存结构的相关分析。


类的内存结构

 

编译环境:ubuntu系统下eclipse

1. 空类

#include <iostream>

using namespace std;

 

//说明一个空类的内存占用 

class class_t 

    {

    };

 

int main() 

{

    class_t obj;

    cout << "Size of obj is = " << sizeof(obj) << endl;

cout << "Address of obj is = " << &obj << endl;

while (1);

    return 0;

}

输出如下:

Size of obj is = 1

Address of obj is = 0xbfc19e0f

编译器在执行class_t obj;这行代码后需要,作出一个class class_t的Object 。而且这个Object的地址是独一无二的,于是编译器就会给空类创建一个隐含的一个字节的空间。

 

 

2. 含成员变量的类

 

#include <iostream>

using namespace std;

 

class point_t {

private:

int m_x;

int m_y;

};

 

int main() {

point_t obj;

cout << "Size of obj is = " << sizeof(obj) << endl;

cout << "Address of obj is = " << &obj << endl;

while (1);

return 0;

}

输出如下:

Size of obj is = 8

Address of obj is = 0xbfaa1c18

对于上述程序,在类定义中加入static T m_z; 输出结果同上,添加了一个静态成员变量,但是Class Size仍然不变。说明静态变量存放在全局/静态区,非静态变量存放在栈上。

加入static void print()class size也不改变,加入一个函数void display()class size也是不改变的,说明函数是不占用类空间的。

int m_y;改为 char m_y;输出结果如下:

Size of obj is = 8

Address of obj is = 0xbfaf2e48

Class size 还是8编译器为了CPU计算,作出的数据对齐处理。

 

3. 含虚函数的类

#include <iostream>

using namespace std;

 

class class_t{

public:

    virtual void fun()

   {

  cout << "Class::fun" << endl; }

};

int main() {

class_t obj;

cout << "Size of obj = " << sizeof(obj) << endl;

cout << "Address of obj = " << &obj << endl;

while (1);

return 0;

}

输出:

Size of obj = 4

Address of obj = 0xbfde8fcc

虚函数表指针占4个字节;但是,对类class_t中再添加几个虚函数,结果还是输出class size 为4,说明虚函表数指针存储了一个虚函数表的地址,其中存储了类中所有虚函数的地址。也就是说,虚函数表是一个数组,这个数组的元素为虚函数指针的地址。

 

4. 含成员变量与虚函数的类

 

3中程序在类中添加如下类成员变量:private:

                                     int m_x;

int m_y;

 则输出为:Size of obj = 12

Address of obj = 0xbfef5054 

 则class size 为成员变量与虚函数所占内存的总和

5. 继承

#include <iostream>

using namespace std;

 

template <typename T>

class point_t {

public:

T m_x;

T m_y;

};

 

template <typename T>

class point3d_t : public point_t<T> {

public:

T m_z;

};

 

int main() {

point_t<int> objPoint;

cout << "Size of object Point is = " << sizeof(objPoint) << endl;

cout << "Address of object Point is = " << &objPoint << endl;

 

point3d_t<int> objPoint3d;

cout << "Size of object Point3D is = " << sizeof(objPoint3d) << endl;

cout << "Address of object Point3D is = " << &objPoint3d << endl;

while (1);

return 0;

}

输出:

Size of object Point is = 8

Address of object Point is = 0xbfc29168

Size of object Point3D is = 12

Address of object Point3D is = 0xbfc2915c

派生类所占据的内存为它本身的数据成员和它基类的成员之和。

 

#include <iostream>

using namespace std;

 

class base1_t {

public:

virtual void f() { }

};

 

class base2_t {

public:

virtual void f() { }

};

 

class base3_t {

public:

virtual void f() { }

};

 

class drive_t : public base1_t, public base2_t, public base3_t {

};

 

int main() {

drive_t obj;

cout << "Size of obj is = " << sizeof(obj) << endl;

while (1);

return 0;

}

输出:

Size of obj is = 12

   当从多个基类继承一个类的时候,这个派生类就会拥有所有基类的虚函数表指针。所以对于类drive_t共有三个虚函数表指针。

   当对以上各类中都加入一个整型成员变量时,结果为28,说明派生类的所占据的内存为它本身的数据成员和它基类的成员之和16派生类就会拥有所有基类的虚函数表指针,占12

   即使在类drive_t中加入另外的虚函数,结果也不变,如下:

#include <iostream>

using namespace std;

class base1_t {

virtual void f() { cout << "Base1::f" << endl; }

virtual void g() { cout << "Base1::g" << endl; }

};

class base2_t {

virtual void f() { cout << "Base2::f" << endl; }

virtual void g() { cout << "Base2::g" << endl; }

};

class base3_t {

virtual void f() { cout << "Base3::f" << endl; }

virtual void g() { cout << "Base3::g" << endl; }

};

 

class drive_t : public base1_t, public base2_t, public base3_t {

public:

virtual void fd() { cout << "Drive::fd" << endl; }

virtual void gd() { cout << "Drive::gd" << endl; }

};

typedef void(*Fun)(void);

 

int main() {

drive_t objDrive;

Fun pFun = NULL;

  // 调用Base1的第一个虚函数

pFun = (Fun)*((int*)*(int*)((int*)&objDrive+0)+0);

pFun();

  // 调用Base1的第二个虚函数

pFun = (Fun)*((int*)*(int*)((int*)&objDrive+0)+1);

pFun();

  // 调用Base2的第一个虚函数

pFun = (Fun)*((int*)*(int*)((int*)&objDrive+1)+0);

pFun();

  // 调用Base2的第二个虚函数

pFun = (Fun)*((int*)*(int*)((int*)&objDrive+1)+1);

pFun();

  // 调用Base3的第一个虚函数

     pFun = (Fun)*((int*)*(int*)((int*)&objDrive+2)+0);

     pFun();

  // 调用Base3的第二个虚函数

     pFun = (Fun)*((int*)*(int*)((int*)&objDrive+2)+1);

     pFun();

  // 调用派生类的第一个虚函数

     pFun = (Fun)*((int*)*(int*)((int*)&objDrive+0)+2);

     pFun();

  // 调用派生类的第二个虚函数

     pFun = (Fun)*((int*)*(int*)((int*)&objDrive+0)+3);

     pFun();

     while (1);

     return 0;

}

 

输出:

Base1::f

Base1::g

Base2::f

Base2::g

Base3::f

Base3::g

Drive::fd

Drive::gd

  说明多重继承时,派生类的虚函数放在第一个父类的虚函数表中,自己不需要再有虚函数表指针,所以上个程序即使在类drive_t中加入另外的虚函数,class size 也不改变。

 

 

6. 虚函数与成员变量的内存分配

 

#include <iostream>

using namespace std;

 

class point_t {

public:

int m_ix;

int m_iy;

point_t(const int p_ix = 0, const int p_iy = 0) :

    m_ix(p_ix), m_iy(p_iy) {

  }

  int get_x() const {

    return m_ix;

  }

  int get_y() const {

    return m_iy;

  }

  virtual ~point_t() { }

};

 

int main() {

point_t objPoint(5, 10);

 

int* pInt = (int*)&objPoint;

*(pInt + 0) = 100; // 改变x的值

*(pInt + 1) = 200; // 改变y的值

cout<<"Size of point_t is = "<<sizeof(objPoint)<<endl;

cout<<"Address of point_t is = "<<&objPoint<<endl;

cout << "X = " << objPoint.get_x() << endl;

cout << "Y = " << objPoint.get_y() << endl;

while(1);

return 0;

}

输出:

Size of point_t is = 12

Address of point_t is = 0xbfc40300

X = 200

Y = 10

 

   Class size 12,即为两个int型成员变量与一个虚析构函数,共12字节。

而把 *(pInt + 0) = 100; // 改变x的值

*(pInt + 1) = 200; // 改变y的值

改为: *(pInt + 1) = 100; // 改变x的值

    *(pInt + 2) = 200; // 改变y的值

则输出为:

Size of point_t is = 12

Address of point_t is = 0xbff063b0

X = 100

Y = 200

说明虚函数表指针就会被添加在存放该类的内存区域中的第一个位置。成员变量分配在后继的位置。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值