类的内存模型 Boolan C++ 第四周

简单的含虚函数的基类和子类

class Fruit
{
   int no;
   double weight;
   char key;
public:
   void print() {   }
   virtual void process(){   }
};

class Apple: public Fruit
{
   int size;
   char type;
public:
   void save() {   }
   virtual void process(){   }
};

由于 定义了虚函数,对于基类和子类,在内存的开头都会有一个指向虚函数表的指针,在32位编译器下,占4字节。

类的内存模型 Boolan C++ 第四周_第1张图片
对象模型.png

派生类继承了基类的全部内存,可以想象成派生类有两部分,一部分是完整的基类数据,另一部分是派生类自己定义的。
加入两个不含虚函数的对照来看

//没有虚函数的继承
class Fruit_not_virtual
{
   int no;
   double weight;
   char key;
public:
   void print() {   }
   void process(){   }
};

class Apple_not_virtual : public Fruit_not_virtual
{
   int size;
   char type;
public:
   void save() {   }
   void process(){   }
};

测试

int main()
{
    cout << "The size of Fruit: " << sizeof(Fruit) << endl;
    cout << "The size of Apple: " << sizeof(Apple) << endl;
    cout << "The size of Fruit_not_virtual: " << sizeof(Fruit_not_virtual) << endl;
    cout << "The size of Apple_not_virtual: " << sizeof(Apple_not_virtual) << endl;
    return 0;
    
}

运行结果

Vs2013运行结果  :
The size of Fruit: 32
The size of Apple: 40
The size of Fruit_not_virtual: 24
The size of Apple_not_virtual: 32   

G++运行结果是    :
The size of Fruit: 20
The size of Apple: 28
The size of Fruit_not_virtual: 16
The size of Apple_not_virtual: 24

输出的原因与数据对齐有很大的关系。
数据对齐就是一种C++中的类型在内存中空间分配策略。每一种类型存储的起始地址,都要求是一个对齐模数的整数倍。目的在于方便CPU处理内存中的数据,提高处理效率。

有一些对齐模数的概念

  1. 自定义类型的自身对齐模数(struct 、class)
    等同于其成员中最大的自身对齐模数
  1. 指定对齐模数
    我们给编译器指定的对齐模数
  2. 有效对齐模数
    有些编译器指定对齐模数与类型自身对齐模数的较小的值,就是实际生效的对齐模数。实际上不同编译器会有差别的。

在Fruit类中自身对齐模数是8字节(double),指定对齐模数一般情况下是处理器位数,32位处理器也就是4字节,以4字节为有效对齐模数。也就是G++的运行结果。VS2013的结果有所不同,查阅网上资料,VS2013的指定的对齐模数是8字节,类型自身对齐模数是8字节时,选择8字节为有效对齐模数,符合上面的运行结果。所以G++和VS2013不同的运算结果是由于编译器指定对齐模式不同引起的。
再来实验一下数据对齐,把所有double类型改为int类型

class Fruit
{
   int no;
   int weight;
   char key;
public:
   void print() {   }
   virtual void process(){   }
};

class Apple: public Fruit
{
   int size;
   int type;
public:
   void save() {   }
   virtual void process(){   }
};

运行结果

Vs2013运行结果  :
The size of Fruit: 16
The size of Apple: 24
The size of Fruit_not_virtual: 12
The size of novirtual_Apple: 20

G++运行结果是    :
The size of Fruit: 16
The size of Apple: 24
The size of Fruit_not_virtual: 12
The size of novirtual_Apple: 20

结果是一致的,应为此时两种编译器的有效对齐模数都是4字节。

你可能感兴趣的:(类的内存模型 Boolan C++ 第四周)