zoukankan      html  css  js  c++  java
  • C++类所占内存大小计算

    C++类所占内存大小计算

    文章出处:http://blog.csdn.net/chenchong08

    作者联系方式:vision_chen@yeah.net

    说明:笔者的操作系统是32位的。

    class A {}; 
    sizeof( A ) = ?
    sizeof( A ) = 1
    明明是空类,为什么编译器说它是1呢?
    空类同样可以实例化,每个实例在内存中都有一个独一无二的地址,为了达到这个目的,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存得到了独一无二的地址.所以sizeof( A )的大小为1.

     
    class B 
    {
    public:
      B() {}
      ~B() {}
      void MemberFuncTest( int para ) { }
      static void StaticMemFuncTest( int para ){  }
    };
    sizeof( B ) = ?
    sizeof( B ) = 1
    类的非虚成员函数是不计算在内的,不管它是否静态。


    class C 
    {
     C(){}
     virtual ~C() {}
    };
    sizeof( B ) = ?
    sizeof( B ) = 4
    类D有一个虚函数,存在虚函数的类都有一个一维的虚函数表叫虚表,虚表里存放的就是虚函数的地址了,因此,虚表是属于类的。这样的类对象的前四个字节是一个指向虚表的指针,类内部必须得保存这个虚表的起始指针。在32位的系统分配给虚表指针的大小为4个字节,所以最后得到类C的大小为4.


    class D 
    {
     D(){}
     virtual ~D() {}
     virtual int VirtualMemFuncTest1()=0;
     virtual int VirtualMemFuncTest2()=0;
     virtual int VirtualMemFuncTest3()=0;
    };
    sizeof( D ) = ?
    sizeof( D ) = 4
    原理同类C,不管类里面有多少个虚函数,类内部只要保存虚表的起始地址即可,虚函数地址都可以通过偏移等算法获得。


    class E
    {
     int  m_Int;
     char m_Char;
    };
    sizeof( E ) = ?
    sizeof( E ) = 8
    32位的操作系统int占4个字节,char占一个字节,加上内存对齐的3字节,为8字节。


    class F : public E
    {
     static int s_data ;
    };
    int F::s_data=100;
    sizeof( F ) = ?
    sizeof( F ) = 8
    类F为什么跟类E一样大呢?类F的静态数据成员被编译器放在程序的一个global data members中,它是类的一个数据成员,但是它不影响类的大小,不管这个类实际产生了多少实例还是派生了多少新的类,静态成员数据在类中永远只有一个实体存在,而类的非静态数据成员只有被实例化的时候,他们才存在.但是类的静态数据成员一旦被声明,无论类是否被实例化,它都已存在.可以这么说,类的静态数据成员是一种特殊的全局变量.


    class G : public E
    {
     virtual int VirtualMemFuncTest1(int para)=0;
     int m_Int;
    };
    class H : public G
    {
     int m_Int;
    };
    sizeof( G ) = ?
    sizeof( H ) = ?
    sizeof( G ) = 16
    sizeof( H ) = 20
    可以看出子类的大小是本身成员的大小再加上父类成员的大小.如果父类还有父类,也加上父类的父类,这样一直递归下去。


    class I : public D
    {
     virtual int VirtualMemFuncTest1()=0;
     virtual int VirtualMemFuncTest2()=0;
    };
    sizeof( I ) = ?
    sizeof( I ) = 4
    父类子类工享一个虚函数指针,虚函数指针保留一个即可。

    总结:
    空的类也是会占用内存空间的,而且大小是1,原因是C++要求每个实例在内存中都有独一无二的地址。
    (一)类内部的成员变量:
    普通的变量:是要占用内存的,但是要注意内存对齐(这点和struct类型很相似)。
    static修饰的静态变量:不占用内存,原因是编译器将其放在全局变量区。
    从父类继承的变量:计算进子类中
    (二)类内部的成员函数:
    非虚函数(构造函数、静态函数、成员函数等):不占用内存。
    虚函数:要占用4个字节(32位的操作系统),用来指定虚拟函数表的入口地址。跟虚函数的个数没有关系。父类子类工享一个虚函数指针。

            构成对象本身的只有数据,任何成员函数都不隶属于任何一个对象,非静态成员函数与对象的关系就是绑定,绑定的中介就是this指针。成员函数为该类所有对象共享,不仅是处于简化语言实现、节省存储的目的,而且是为了使同类对象有一致的行为。同类对象的行为虽然一致,但是操作不同的数据成员。

     

    测试代码如下:

    1. <span style="font-size:18px;">/* 
    2.  * file name   : main.cpp 
    3.  * description : test the size of c++'s class 
    4.  * create on   : 2012-05-31 
    5.  * create by   : chenchong 
    6.  * email         : vision_chen@yeah.net 
    7.  */  
    8.   
    9. #include<iostream>  
    10.   
    11. using namespace std;  
    12.   
    13. class A {};   
    14.   
    15. class B   
    16. {  
    17. public:  
    18.   B() {}  
    19.   ~B() {}  
    20.   void MemberFuncTest( int para ) { }  
    21.   static void StaticMemFuncTest( int para ){  }  
    22. };  
    23.   
    24. class C   
    25. {  
    26.  C(){}  
    27.  virtual ~C() {}  
    28. };  
    29.   
    30. class D   
    31. {  
    32.  D(){}  
    33.  virtual ~D() {}  
    34.  virtual int VirtualMemFuncTest1()=0;  
    35.  virtual int VirtualMemFuncTest2()=0;  
    36.  virtual int VirtualMemFuncTest3()=0;  
    37. };  
    38.   
    39. class E  
    40. {  
    41.  int  m_Int;  
    42.  char m_Char;  
    43. };  
    44.   
    45. class F : public E  
    46. {  
    47.  static int s_data ;  
    48. };  
    49. int F::s_data=100;  
    50.   
    51. class G : public E  
    52. {  
    53.  virtual int VirtualMemFuncTest1(int para)=0;  
    54.  int m_Int;  
    55. };  
    56. class H : public G  
    57. {  
    58.  int m_Int;  
    59. };  
    60.   
    61. class I : public D  
    62. {  
    63.  virtual int VirtualMemFuncTest1()=0;  
    64.  virtual int VirtualMemFuncTest2()=0;  
    65. };  
    66.   
    67. int main( int argc, char **argv )  
    68. {  
    69.  cout<<"sizeof( A ) = "<<sizeof( A )<<endl;  
    70.  cout<<"sizeof( B ) = "<<sizeof( B )<<endl;  
    71.  cout<<"sizeof( C ) = "<<sizeof( C )<<endl;  
    72.  cout<<"sizeof( D ) = "<<sizeof( D )<<endl;  
    73.  cout<<"sizeof( E ) = "<<sizeof( E )<<endl;  
    74.  cout<<"sizeof( F ) = "<<sizeof( F )<<endl;  
    75.  cout<<"sizeof( G ) = "<<sizeof( G )<<endl;  
    76.  cout<<"sizeof( H ) = "<<sizeof( H )<<endl;  
    77.  cout<<"sizeof( I ) = "<<sizeof( I )<<endl;  
    78.   
    79. #if defined( _WIN32 )  
    80.  system("pause");  
    81. #endif  
    82.  return 0;  
    83. }  
    84.   
    85. </span>  


     

    Windows 7 32位 VC 2010运行结果:

    Linux(cent os 6.2 32位)运行结果:

     




  • 相关阅读:
    Express 2015 RC for Windows 10 安装
    离线下载Express 2015 for Windows 10
    离线下载Express 2015 for Windows 10
    windows 10预览版升级win10 7月29 10240.16384
    windows 10预览版升级win10 7月29 10240.16384
    C# 获得系统环境
    C# 获得系统环境
    C++宽字符串转字符串
    C++宽字符串转字符串
    C++ md5类,封装好
  • 原文地址:https://www.cnblogs.com/fengty90/p/3768851.html
Copyright © 2011-2022 走看看