初学者在学习面向对象的程序设计语言时,或多或少的都些疑问,我们写的代码与最终生编译成的代码却大相径庭,我们并不知道编译器在后台做了什么工作.这些都是由于我们仅停留在语言层的原因,所谓语言层就是教会我们一些基本的语法法则,但不会告诉我们为什么这么做?今天和大家谈的一点感悟就是我在学习编程过程中的一点经验,是编译器这方面的一个具体功能.

首先:我们要知道什么是类的实例化,所谓类的实例化就是在内存中分配一块地址.

那我们先看看一个例子:

#include<iostream.h>

class a {};

class b{};

class c:public a{

  virtual void fun()=0;

};

class d:public b,public c{

};

int main()

{

  cout<<"sizeof(a)"<<sizeof(a)<<endl;

  cout<<"sizeof(b)"<<sizeof(b)<<endl;

  cout<<"sizeof(c)"<<sizeof(c)<<endl;

  cout<<"sizeof(d)"<<sizeof(d)<<endl;

  return  0;

}

程序执行的输出结果为:

sizeof(a) =1

sizeof(b)=1

sizeof(c)=4

sizeof(d)=8

为什么会出现这种结果呢?初学者肯定会很烦恼是吗?类a,b明明是空类,它的大小应该为为0,为什么 编译器输出的结果为1呢?这就是我们刚才所说的实例化的原因(空类同样可以被实例化),每个实例在内存中都有一个独一无二的地址,为了达到这个目的,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存得到了独一无二的地址.所以a,b的大小为1.

而类c是由类a派生而来,它里面有一个纯虚函数,由于有虚函数的原因,有一个指向虚函数的指针(vptr),在32位的系统分配给指针的大小为4个字节,所以最后得到c类的大小为4.

类d的大小更让初学者疑惑吧,类d是由类b,c派生迩来的,它的大小应该为二者之和5,为什么却是8  呢?这是因为为了提高实例在内存中的存取效率.类的大小往往被调整到系统的整数倍.并采取就近的法则,里哪个最近的倍数,就是该类的大小,所以类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

它们的结果均相同,可以看出类的大小与它当中的构造函数,析构函数,以及其他的成员函数无关,只与它当中的成员数据有关.

从以上的几个例子不难发现类的大小:

1.为类的非静态成员数据的类型大小之和.

2.有编译器额外加入的成员变量的大小,用来支持语言的某些特性(如:指向虚函数的指针).

3.为了优化存取效率,进行的边缘调整.

4 与类中的构造函数,析构函数以及其他的成员函数无关.

参考链接:http://blog.csdn.net/hitblue/article/details/3726754

c++空类的大小的更多相关文章

  1. 转:C/C++中,空数组、空类、类中空数组的解析及其作用

    转自:http://blog.sina.com.cn/s/blog_93b45b0f01015s95.html 我们经常会遇到这些问题: (1)C++中定义一个空类,他们它的大小(sizeof) 为多 ...

  2. C++类的大小计算汇总

    C++中类涉及到虚函数成员.静态成员.虚继承.多继承.空类等. 类,作为一种类型定义,是没有大小可言的. 类的大小,指的是类的对象所占的大小.因此,用sizeof对一个类型名操作,得到的是具有该类型实 ...

  3. C++类的大小——sizeof(class)

    第一:空类的大小 class CBase { }; 运行cout<<"sizeof(CBase)="<<sizeof(CBase)<<endl; ...

  4. C/C++中,空数组、空类、类中空数组的解析及其作用

    转自:http://blog.sina.com.cn/s/blog_93b45b0f01015s95.html 我们经常会遇到这些问题: (1)C++中定义一个空类,他们它的大小(sizeof) 为多 ...

  5. C++中的空类与空结构体大小

    今天面试遇到了一个很有意思的问题,即空结构体在C++中所占的内存大小是多少?参见如下代码: #include <iostream> struct S0 { }; int main() { ...

  6. C++空类以及没有成员变量的类的大小

    关于C++中空类的大小为1,我们大家都有所了解,但是除了空类之外的其他一些没有成员变量的类的大小,还是有很多不明之处的. 我们来看如下一个例子: #include<iostream> us ...

  7. C++空类大小

    class a {};class b{};class c:public a{ virtual void fun()=0;};class d:public b,public c{}; 类a,b明明是空类 ...

  8. C/C++中的空类及抽象类大小

    代码: #include <iostream> using namespace std; struct A{ }; struct B{ int i; }; class C:B{ ; }; ...

  9. 类的大小——sizeof 的研究

    类的大小——sizeof 的研究(1) 先看一个空的类占多少空间? class Base { public: Base(); ~Base(); }; 注意到我这里显示声明了构造跟析构,但是sizeof ...

随机推荐

  1. 火狐restclient

    RESTClient是一款用于测试各种Web服务的插件,它可以向服务器发送各种HTTP请求(用户也可以自定义请求方式),并显示服务器响应.使用RESTClient您可以方便的测试各种Web服务,为您的 ...

  2. nagios–配置文件

    ngios的配置文件位于/etc/nagios目录下 # ll /etc/nagios 总用量 -rw-rw-r-- nagios nagios 3月 : cgi.cfg -rw-r--r-- roo ...

  3. 【STL】全排列生成算法:next_permutation

    C++/STL中定义的next_permutation和prev_permutation函数是非常灵活且高效的一种方法,它被广泛的应用于为指定序列生成不同的排列. next_permutation函数 ...

  4. 转:Linux网络IO并行化技术概览

    转:http://codinginet.com/articles/view/201605-linux_net_parallel?simple=1&from=timeline&isapp ...

  5. 转: 基于nginx的hls直播系统

    转自:http://blog.csdn.net/cjsafty/article/details/9108587 看点: 1. 详细解解答了 nginx rtmp配置过程. 前写了一篇基于nginx的h ...

  6. JMS - Temporary Destination

    Although sessions are used to create temporary destinations, this is only for convenience. Their sco ...

  7. JMS - Exceptions

    The JMSException JMS defines JMSException as the root class for exceptions thrown by JMS methods. JM ...

  8. Ubuntu 14.0操作系统,修改默认打开方式的方法

    Ubuntu 14.0 有内置的视频播放器 Totem,但是使用起来不太习惯,所以在系统的软件中心 下载了gnome Mplayer和s Mplayer,都有打开上次播放的忆功能,只是gnome Mp ...

  9. Is it possible to change the iPhone device name programmatically?

    今天刚好方案公司谈到一个需求方案,要制作一个dvr连接手机,手机能上网的功能. 为了简化,让dvr开机轮询,连接某个iphone设备名字特征的手机,希望在app中提供一个输入框,可以 按dvr可以识别 ...

  10. hdoj1423 最长上升公共子序列

    hdoj1423 题目分析: 两个数组a[n1] , b[n2], 求最长上升公共子序列. 我们可用一维存储 f[i] 表示 b 数组以 j 结尾, 与 a[] 数组构成的最长公共上升子序列. 对数组 ...