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大小。
  • 相关阅读:
    电商用户留存率比例
    转载——使用Python拆分数据量大的CSV文件(亲测有效)
    SQL中group by的注意事项
    MySQL中DELETE子句与TRUNCATE TABLE语句的区别
    TimeStamp( )函数, TimeStampAdd( )函数 , TimeStampDiff( )函数
    MySQL 练习题目 二刷
    math对象,BOM模型中常用对象
    js函数和date内置对象
    while循环和for循环
    不等于运算符、逻辑表达式、if语句及switch语句
  • 原文地址:https://www.cnblogs.com/noble/p/4144019.html
Copyright © 2011-2022 走看看