C++类的大小(转)

一个空类class A{};的大小为什么是1,因为如果不是1,当定义这个类的对象数组时候A objects[5]; objects[0]和objects[1]就在同一个地址处,就无法区分。

单继承

复制代码
 1 #include<iostream>
 2 using namespace std;
 3 class A
 4 {
 5 public:
 6     virtual void aa(){}
 7 private:
 8     char k[3];
 9 };
10 
11 class B: public A
12 {
13 public:
14     virtual void bb(){}
15 };
16 
17 int main()
18 {
19     cout<<"A's size is "<<sizeof(A)<<endl;
20     cout<<"B's size is "<<sizeof(B)<<endl;
21     return 0;
22 }
复制代码

 

vs和gcc下
执行结果:A's size is 8
              B's size is 8

说明:有虚函数的类有个virtual table(虚函数表),里面包含了类的所有虚函数,类中有个virtual table pointers,通常成为vptr指向这个virtual table,占用4个字节的大小。成员类B public继承于A,类B的虚函数表里实际上有两个虚函数A::aa()和B::bb(),类B的大小等于char k[3]的大小加上一个指向虚函数表指针vptr的大小,考虑内存对齐为8。

复制代码
 1 #include<iostream>
 2 using namespace std;
 3 class A
 4 {
 5 public:
 6     virtual void aa(){}
 7 private:
 8     char k[3];
 9 };
10 
11 class B: public A
12 {
13 public:
14     //virtual void bb(){}
15 };
16 
17 int main()
18 {
19     cout<<"A's size is "<<sizeof(A)<<endl;
20     cout<<"B's size is "<<sizeof(B)<<endl;
21     return 0;
22 }
复制代码

 

vs和gcc下
执行结果:A's size is 8
              B's size is 8
说明:类B看上去没有虚函数,但实际上它有,只是没有重写,因为public继承,所以有从A继承过来的虚函数A::aa(),实际上类A和类B的虚函数表里的函数都是A::aa()。

复制代码
 1 #include<iostream>
 2 using namespace std;
 3 class A
 4 {
 5 public:
 6     virtual void aa(){}
 7     virtual void aa2(){}
 8 private:
 9     char k[3];
10 };
11 
12 class B: public A
13 {
14 public:
15     virtual void bb(){}
16     virtual void bb2(){}
17 };
18 
19 int main()
20 {
21     cout<<"A's size is "<<sizeof(A)<<endl;
22     cout<<"B's size is "<<sizeof(B)<<endl;
23     return 0;
24 }
复制代码

 

vs和gcc下
执行结果:A's size is 8
              B's size is 8

说明:一个类里若有虚函数,无论有多少个虚函数都只有一个指向虚表的指针,虚表中的每一个表项保存着一个虚函数的入口地址。当调用虚函数时,先找到虚表中它对应的表项,找到入口地址再执行。对于直接单继承,无论类B中有无虚函数,由于它继承了类A,且类A里含有虚函数,因此如果类B有虚函数,那么它和类A的是在同一个属于类B的虚表里,这张虚表的虚函数为A::aa()、A::aa2()、B::bb()、B::bb2()。注意:类A里的私有成员在类B里仍占有内存。

多继承

复制代码
 1 #include<iostream>
 2 using namespace std;
 3 class A
 4 {
 5 public:
 6     virtual void aa(){}
 7     virtual void aa2(){}
 8 private:
 9     char k[3];
10 };
11 
12 class B
13 {
14 public:
15     virtual void bb(){}
16     virtual void bb2(){}
17 };
18 
19 class C: public A,public B
20 {
21 public:
22     virtual void aa(){} //重写了A的aa()
23     virtual void cc(){}
24 };
25 
26 int main()
27 {
28     cout<<"A's size is "<<sizeof(A)<<endl;
29     cout<<"B's size is "<<sizeof(B)<<endl;
30     cout<<"C's size is "<<sizeof(C)<<endl;
31     return 0;
32 }
复制代码

 

vs和gcc下
执行结果:A's size is 8
          B's size is 8
          B's size is 16

说明:类A和B的大小就不解释了,参照上面。类C多重继承于A和B(有虚函数覆盖),那么类C的大小是多少?先看成员变量,有一个继承A的char k[3]。再看虚函数,类C的中虚函数是怎么分布的?先有一个虚函数表,里面有继承于类A的虚函数和C自己的虚函数(C::aa(), A::aa2(), C::cc()),如果C没有重写aa(),那么第一个虚函数就是A::aa(),以及k[3],接着有第二张虚函数表是继承包含类B的虚函数B::bb()、B::bb2()(类C没有重写B的虚函数)以及k[3]。总的大小就是2张虚表的大小(也即两个虚函数指针的大小)8字节加上3字节的k[3]*2,考虑内存对齐,就是16字节。

虚继承

复制代码
 1 #include<iostream>
 2 using namespace std;
 3 class A
 4 {
 5 public:
 6     virtual void aa(){}
 7 private:
 8     char k[3];
 9 };
10 
11 class B: virtual public A
12 {
13 public:
14     //virtual void bb(){}
15 };
16 
17 int main()
18 {
19     cout<<"A's size is "<<sizeof(A)<<endl;
20     cout<<"B's size is "<<sizeof(B)<<endl;
21     return 0;
22 }
复制代码

 

vs和gcc下
执行结果:A's size is 8
              B's size is 12
说明:类B里包含,继承的char k[3],继承的虚函数,类B的虚函数表里有A::aa(),因为是虚继承,还有一个指向父类的指针,该指针为指向虚基类的指针(Pointer to virtual base class)。考虑内存对齐,总大小为12。

复制代码
 1 #include<iostream>
 2 using namespace std;
 3 class A
 4 {
 5 public:
 6     virtual void aa(){}
 7 private:
 8     char k[3];
 9 };
10 
11 class B: public virtual A
12 {
13 public:
14     virtual void bb(){}
15 };
16 
17 int main()
18 {
19     cout<<"A's size is "<<sizeof(A)<<endl;
20     cout<<"B's size is "<<sizeof(B)<<endl;
21     return 0;
22 }
复制代码

 

VS执行结果:A's size is 8
                  B's size is 16

gcc执行结果:A's size is 8
                  B's size is 12

说明:对于虚继承,类B虚继承类A时,首先要通过加入一个指针来指向父类A,该指针被称为虚基类指针。然后包含从父类继承过来的3个char,再加上一个虚函数指针。考虑内存对齐,在gcc下结果是4+4+4=12。在VS下,结果是16,why?这一题和上一题区别只是在类B中添加了一个虚函数,但是两个题目中类B都有虚函数表。在VS下调试查看汇编代码,发现多出来的4字节什么也没有。

 

转自:http://www.cnblogs.com/luxiaoxun/archive/2012/09/01/2666395.html

posted @   鸭子船长  阅读(250)  评论(0编辑  收藏  举报
编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示