zoukankan      html  css  js  c++  java
  • 类的大小

    转自类的大小——sizeof 的研究(1)

           类的大小——sizeof 的研究(2.虚函数继承)

    先看一个空的类占多少空间?

    1. class Base  
    2. {  
    3. public:  
    4.     Base();  
    5.     ~Base();  
    6.   
    7. };  

        注意到我这里显示声明了构造跟析构,但是sizeof(Base)的结果是1.

         因为一个空类也要实例化,所谓类的实例化就是在内存中分配一块地址,每个实例在内存中都有独一无二的地址。同样空类也会被实例化,所以编译器会给空类隐含的添加一个字节,这样空类实例化之后就有了独一无二的地址了。所以空类的sizeof为1。

       而析构函数,跟构造函数这些成员函数,是跟sizeof无关的,也不难理解因为我们的sizeof是针对实例,而普通成员函数,是针对类体的,一个类的成员函数,多个实例也共用相同的函数指针,所以自然不能归为实例的大小,这在我的另一篇博文有提到。


       接着看下面一段代码

    1. class Base  
    2. {  
    3. public:  
    4.     Base();                  
    5.     virtual ~Base();         //每个实例都有虚函数表  
    6.     void set_num(int num)    //普通成员函数,为各实例公有,不归入sizeof统计  
    7.     {  
    8.         a=num;  
    9.     }  
    10. private:  
    11.     int  a;                  //占4字节  
    12.     char *p;                 //4字节指针  
    13. };  
    14.   
    15. class Derive:public Base  
    16. {  
    17. public:  
    18.     Derive():Base(){};       
    19.     ~Derive(){};  
    20. private:  
    21.     static int st;         //非实例独占  
    22.     int  d;                     //占4字节  
    23.     char *p;                    //4字节指针  
    24.   
    25. };  
    26.   
    27. int main()   
    28. {   
    29.     cout<<sizeof(Base)<<endl;  
    30.     cout<<sizeof(Derive)<<endl;  
    31.     return 0;  
    32. }  

    结果自然是

    12

    20

    Base类里的int  a;char *p;占8个字节。

    而虚析构函数virtual ~Base();的指针占4子字节。

    其他成员函数不归入sizeof统计。

    Derive类首先要具有Base类的部分,也就是占12字节。

    int  d;char *p;占8字节

    static int st;不归入sizeof统计

    所以一共是20字节。

     

    在考虑在Derive里加一个成员char c;

    1. class Derive:public Base  
    2. {  
    3. public:  
    4.     Derive():Base(){};  
    5.     ~Derive(){};  
    6. private:  
    7.     static int st;  
    8.     int  d;  
    9.     char *p;  
    10.     char c;  
    11.   
    12. };  

    这个时候,结果就变成了

    12

    24

    一个char c;增加了4字节,说明类的大小也遵守类似class字节对齐,的补齐规则。

     

    我们再结合虚函数表,来研究下类的大小。

    1. class Base  
    2. {  
    3. public:  
    4.     Base(){};  
    5.     virtual ~Base(){};  
    6.     void set_num(int num)  
    7.     {  
    8.         a=num;  
    9.     }  
    10.     virtual int get_num()  
    11.     {  
    12.         return a;  
    13.     }  
    14. private:  
    15.     int  a;  
    16.     char *p;  
    17. };  
    18.   
    19. class Derive:public Base  
    20. {  
    21. public:  
    22.     Derive():Base(){};  
    23.     ~Derive(){};  
    24.          virtual int get_num()  
    25.     {  
    26.         return d;  
    27.     }  
    28. private:  
    29.     static int st;  
    30.          int  d;  
    31.          char *p;  
    32.     char c;  
    33.   
    34. };  
    35.   
    36. int main()   
    37. {   
    38.     cout<<sizeof(Base)<<endl;  
    39.     cout<<sizeof(Derive)<<endl;  
    40.     return 0;  
    41. }  

    在Base类里添加了virtual int get_num()函数,而子类也重新实现了virtual int get_num()函数。

    但是结果依然是

    12

    24

    说明子类只是共用父类的虚函数表,因此一旦父类里有虚函数,子类的虚函数将不计入sizeof大小。


    至此,我们可以归纳以下几个原则:

    1.类的大小为类的非静态成员数据的类型大小之和,也就是说静态成员数据不作考虑。

    2.普通成员函数与sizeof无关。

    3.虚函数由于要维护在虚函数表,所以要占据一个指针大小,也就是4字节。

    4.类的总大小也遵守类似class字节对齐的,调整规则。

    5.一旦父类里有虚函数,子类的虚函数将不计入sizeof大小。
  • 相关阅读:
    Java的静态块与实例块(转)
    Programming Ability Test学习 1031. Hello World for U (20)
    Programming Ability Test学习 1011. World Cup Betting (20)
    Programming Ability Test学习 1027. Colors in Mars (20)
    Programming Ability Test学习 1064. Complete Binary Search Tree (30)
    Programming Ability Test学习 1008. Elevator (20)
    【maven详解-生命周期】Maven的生命周期和插件
    【maven详解-插件】maven插件学习之源码插件Source Xref
    $(document).ready(){}、$(fucntion(){})、(function(){})(jQuery)onload()的区别
    你还没真的努力过,就轻易输给了懒惰
  • 原文地址:https://www.cnblogs.com/noble/p/4144019.html
Copyright © 2011-2022 走看看