转载)

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

初学者在学习面向对象的程序设计语言时,或多或少的都些疑问,我们写的代码

如:

与最终生编译成的代码却 大相径庭,我们并不知道编译器在后台做了什么工作

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;
};

#include<iostream.h>

sizeof(A)是12.

class a {};

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

class b{};

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

class c:public a{

 

virtual void fun()=0;

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;}
};

class d:public b,public c{};

sizeof(Base)为8.

int main()

 

{

澳门新葡萄京官网首页,4、对于子类,它的sizeof是它父类成员(无论成员是public或private),再加上它自己的成员,对齐后的sizeof,如:

cout<<“sizeof(a)”<<sizeof(a)<<endl;

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

cout<<“sizeof(b)”<<sizeof(b)<<endl;

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

cout<<“sizeof(c)”<<sizeof(c)<<endl;

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

cout<<“sizeof(d)”<<sizeof(d)<<endl;

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

return 0;}

sizeof(A3)是12.

程序执行的输出结果为:

 

sizeof(a) =1

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

sizeof(b)=1

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(c)=4

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

sizeof(d)=8

sizeof(Derived)是12.

为什么会出现这种结果呢?初学者肯定会很烦恼是吗?类a,b明明是空类,它的

 

大小应该为为0,为什么 编译器输出的结果为1呢?这就是我们刚才所说的实

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。

类在实例化后在内存得到了独一无二的地址.所以a,b的大小为1.

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

而类c是由类a派生而来,它里面有一个纯虚函数,由于有虚函数的原因,有一个

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

指向虚函数的指针(vptr),在32位的系统分配给指针的大小为4个字节,所

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;}
};

以最后得到c类的大小为4.

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

类d的大小更让初学者疑惑吧,类d是由类b,c派生迩来的,它的大小应该为二者

sizeof(Base)=4

之和5,为什么却是8 呢?这是因为为了提高实例在内存中的存取效率.类

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

的大小往往被调整到系统的整数倍.并采取就近的法则,里哪个最近的倍数,就

是该类的大小,所以类d的大小为8个字节.

当然在不同的编译器上得到的结果可能不同,但是这个实验告诉我们初学者,不

管类是否为空类,均可被实例化(空类也可被实例化),每个被实例都有一个独

一无二的地址.

我所用的编译器为vc++ 6.0.

下面我们再看一个例子.

#include<iostream.h>

class a{

pivate:

int data;

};

class b{

private:

int data;

static int data1;

};

int b::data1=0;

void mian(){

cout<<“sizeof(a)=”<<sizeof(a)<<endl;

cout<<“sizeof(b)=”<<sizeof(b)<<endl;

}

执行结果为:

sizeof(a)=4;

sizeof(b)=4;

为什么类b多了一个数据成员,却大小和类a的大小相同呢?因为:类b的静态数据

成员被编译器放在程序的一个global data members中,它是类的一个数据成员

.但是它不影响类的大小,不管这个类实际产生 了多少实例,还是派生了多少

新的类,静态成员数据在类中永远只有一个实体存在,而类的非静态数据成员只

有被实例化的时候,他们才存在.但是类的静态数据成员一旦被声明,无论类是

否被实例化,它都已存在.可以这么说,类的静态数据成员是一种特殊的全局变

量.

所以a,b的大小相同.

下面我们看一个有构造函数,和析构函数的类的大小,它又是多大呢?

#include<iostream.h>

class A{

public :

A(int a){

a=x;}

void f(int x){

cout<<x<<endl;}

~A(){}

private:

int x;

int g;

};

class B{

public:

private:

int data; int data2;

static int xs;

};

int B::xs=0;

void main(){

A s(10);

s.f(10);

cout<<“sozeof(a)”<<sizeof(A)<<endl;

cout<<“sizeof(b)”<<sizeof(B)<<endl;

}程序执行输出结果为:

10 ,

sizeof(a) 8

sizeof(b) 8

它们的结果均相同,可以看出类的大小与它当中的构造函数,析构函数,以及其

他的成员函数无关,只与它当中的成员数据有关