sizeof

数据对齐

数组的sizeof值等于数组所占用的内存字节数,如: 
  char a1[] = "abc"; 
  int a2[3]; 
  sizeof( a1 ); // 结果为4,字符 末尾还存在一个NULL终止符 
  sizeof( a2 ); // 结果为3*4=12(依赖于int 
  一些朋友刚开始时把sizeof当作了求数组元素的个数,现在,你应该知道这是不对的,那么应该怎么求数组元素的个数呢Easy,通常有下面两种写法: 
  int c1 = sizeof( a1 ) / sizeof( int ); // 总长度/单个元素的长度 
  int c2 = sizeof( a1 ) / sizeof( a1[0] ); // 总长度/第一个元素的长度 
  写到这里,提一问,下面的c3c4值应该是多少呢 
  void foo3(char a3[3]) 
  
  int c3 = sizeof( a3 ); // c3 == 
  
  void foo4(char a4[]) 
  
  int c4 = sizeof( a4 ); // c4 == 
  
  也许当你试图回答c4的值时已经意识到c3答错了,是的,c3!=3。这里函数参数a3已不再是数组类型,而是蜕变成指针,相当于char* a3,为什么仔细想想就不难明白,我们调用函数foo1时,程序会在栈上分配一个大小为3的数组吗不会!数组是传址的,调用者只需将实参的地址传递过去,所以a3自然为指针类型(char*),c3的值也就为4

类的sizeof大小一般是类中的所有成员的sizeof大小之和,这个就不用多说。
不过有两点需要注意:1)当类中含有虚成员函数的时候,例如:
class B
{
float a;
public:
virtual void fun(void);
}
此时sizeof(B)的大小为8,而不是4。因为在类中隐藏了一个指针,该指针指向虚函数表,正因为如此,
使得C++能够支持多态,即在运行时绑定函数的地址。
2
)另一个要注意的是,当类中没有任何成员变量,也没有虚函数的时候,该类的大小是多少呢?
例如:
class B2
{
void fun(void);
}
此时sizeof(B2)的值是多少呢?在C++早期的编译器中,这个值为0;然而当创建这样的对象时,
它们与紧接着它们后面的对象有相同的地址。比如:
B2 b2;
int a;
那么对象b2与变量a有相同的地址,这样的话对对象b2地址的操作就会影响变量a。所以在现在大多数编译器中,该值的大小为1


如果有虚函数,则sizeof值为类的数据成员的大小加上VTBL(指针,4字节),再加上其基类的数据成员的大小。如果是多重继承,还得加上各基类的VTBL


虚继承之单继承的内存布局

先看一段代码
class A
{
      virtual aa(){};
};

class B : public virtual  A
{
      char j[3];                                    //加入一个变量是为了看清楚class中的vfptr放在什么位置
      public:
            virtual bb(){};
};
class C : public virtual B
{
      char i[3];
      public:
            virtual cc(){};
};

这次先不给结果,先分析一下,也好加强一下印象。
1
、对于class A,由于只有一个虚函数,那么必须得有一个对应的虚函数表,来记录对应的函数入口地址。同时在class A的内存空间中之需要有个vfptr_A指向该表。sizeofA)也很容易确定,为4
2
、对于class B,由于class B虚基础了class A,同时还拥有自己的虚函数。那么class B中首先拥有一个vfptr_B,指向自己的虚函数表。还有char j[3],做一次alignment,一般大小为4。可虚继承该如何实现咧?首先要通过加入一个虚l类指针(记vbptr_B_A)来指向其父类,然后还要包含父类的所有内容。有些复杂了,不过还不难想象。sizeofB= 444416vfptr_Bchar j[3]alignmentvbptr_B_Aclass A)。
3
、在接着是class C了。class C首先也得有个vfptr_C,然后是char i[3],然后是vbptr_C_B,然后是class B,所以sizeofC)=4441628vfptr_Cchar i[3]alignmentvbptr_C_Aclass B)。

VC 6.0下写了个程序,把上面几个类的大小打印出来,果然结果为41628

VC中虚继承的内存布局——单继承
画了个图,简单表示一下我跟踪后的结果

pastedGraphic.png
虚基础之单继承时的内存布局图


1、空类的sizeof1。空类是指没有成员的类,类中的函数不占空间,除非是虚函数。

如: class A

        {

             public:

                      A(){}

                     ~A(){}

                     void fun(){}

         };

sizeof(A)1.

注: class A1

        {

             public:

                      A1(){}

                     ~A1(){}

                     void fun(){}

                       char a[0];

         };

sizeof(A1)也是1.VC6.0下编译)

2、若类中包含成员,则类对象的大小只包括其中非静态成员经过对齐所占的空间,对齐方式和结构体相同。如:

class A
{
public:
  int b;
  float c;
  char d;
};

sizeof(A)12.

class A
{
public:
  static int a;
  int b;
  float c;
  char d;
};
sizeof(A)12.

class A
{
public:
  static int a;
  int b;
  float c;
  char d;
  int add(int x,int y)
  {
    return x+y;
  }
};
sizeof(A)也是12.

 

3、若类中包含虚函数,则无论有几个虚函数,sizeof类都等于sizeof(数据成员)的和+sizeof(V表指针,为4),如:

class Base
{
      public:
             Base(){cout<<"Base-ctor"<<endl;}
             ~Base(){cout<<"Base-dtor"<<endl;}
             int a;
             virtual void f(int) {cout<<"Base::f(int)"<<endl;}
             virtual void f(double){cout<<"Base::f(double)"<<endl;}
};

sizeof(Base)8.

 

4、对于子类,它的sizeof是它父类成员(无论成员是publicprivate),再加上它自己的成员,对齐后的sizeof,如:

class A2
{
      public:
             int a;
      private:
              char b;
};

class A3:public A2
{
      public:
             char b;
             short a;             
};

sizeof(A3)8. 但如果A3如下:

class A3:public A2
{
      public:
             short a;  
             char b;           
};

sizeof(A3)12.

 

5、对于子类和父类中都有虚函数的情况,子类的sizeof是它父类成员(无论成员是publicprivate),再加上它自己的成员,对齐后的sizeof,再加4(虚表指针)。如:

class Base
{
      public:
             Base(){cout<<"Base-ctor"<<endl;}
             ~Base(){cout<<"Base-dtor"<<endl;}
             int a;
             virtual void f(int) {cout<<"Base::f(int)"<<endl;}
             virtual void f(double){cout<<"Base::f(double)"<<endl;}
};

class Derived:public Base
{
  public:
         Derived(){cout<<"Derived-ctor"<<endl;}
         int b;
         virtual void g(int){cout<<"Derived::g(int)"<<endl;}
};

sizeof(Derived)12.

 

6、对于虚继承的子类,其sizeof的值是其父类成员,加上它自己的成员,以及它自己一个指向父类的指针(大小为4),对齐后的sizeof。如:

#include   <iostream.h>   
    
  class   a   
  {   
  private:   
  int   x;   
  };   
    
    
    
  class   b:   virtual   public   a   
  {   
  private:   
  int   y;   
  };   
    
  class   c:   virtual   public   a   
  {   
  private:   
  int   z;   
  };   
    
  class   d:public   b,public   c   
  {   
  private:   
  int   m;   
  };   
  int   main(int   argc,   char*   argv[])   
  {   
  cout<<sizeof(a)<<endl;   
  cout<<sizeof(b)<<endl;   
  cout<<sizeof(c)<<endl;   
  cout<<sizeof(d)<<endl;   
  return   0;   
  }   
    VC6.0下调试结果为   
  4   
  12   
  12   
  24

sizeof(b)sizeof(c)相同,都是4+4+4=12

sizeof(d)sizeof(b)(12)+sizeof(c)(12-bc相同的部分(a的成员,大小是4+d自己的成员(大小为4=24

7、对于既有虚继承又有虚函数的子类,其sizeof的值是其父类成员(计算虚表指针大小+4),加上它自己的成员(计算虚表指针大小+4),以及它自己一个指向父类的指针(大小为4),对齐后的sizeof

class Base
{
public:
 Base(){cout<<"Base-ctor"<<endl;}
 ~Base(){cout<<"Base-dtor"<<endl;}
 virtual void f(int) {cout<<"Base::f(int)"<<endl;}
virtual void f(double){cout<<"Base::f(double)"<<endl;}
};

class Derived:virtual public Base
{
public:
 Derived(){cout<<"Derived-ctor"<<endl;}
 virtual void g(int){cout<<"Derived::g(int)"<<endl;}
};

sizeofBase=4

sizeofDerived=12 (父类虚表指针大小4+自己虚表指针大小4+子类指向父类的一个指针大小4=12)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值