一个类到底有多大?

我们知道一个int型、char型或一个结构体,我们都能大致的知道他的大小,那么一个类的大小你能否知道呢?下面看一个例子

 #include <iostream>
  2 
  3 using namespace std;
  4 
  5 /*struct st
  6 {
  7     char ch;
  8     int  in;
  9 };
 10 */
 11 class X {};
 12 
 13 class Y:public virtual X {};
 14 
 15 class Z:public virtual X {};
 16 
 17 class A:public Y, public Z {};
 18 
 19 int main()
 20 {   
 21 //  cout << sizeof(st) << endl;
 22     cout << sizeof(X) << endl;
 23     cout << sizeof(Y) << endl;
 24     cout << sizeof(Z) << endl;
 25     cout << sizeof(A) << endl;
 26     return 0;
 27 }

  上面的结果会是多少呢?下面是输出结果(笔者机器上的 int 是 4 个字节)

  一定很令你惊讶,为什么都是空类,最后类的大小却是这样呢?下面我来一一解释!

  X:X事实上不是空的,它有有一个隐晦的 1 byte。这使得这个 class 的两个 objects 得以在内存中配置独一无二的地址。否则类似if( &a==&b ) 不就永远成立了嘛,这个我在我的另一篇博文中也有讲过,就不多说了,也很好理解!

  最让人费解的是 Y 和 Z 的大小,其实 X 和 Y 的大小受到三个因素的影响:

  (1). 语言本身所造成的额外负担(overload)。当语言支持 virtual base class 时,就会导致一些额外负担,在derived class 中这个额外的负担反映在某种形式的指针上。

  (2). 编译器对对于特殊情况所提供处理。比如 X 中的 1 byte 的出现,并继承到以后的类中!

  (3). Alignment (边界调整 )的限制。

  在本例中,X 和 Y的大小是 4个字节,那是因为编译器对继承而来的 X 进一步优化了。不优化的编译器上,Y 和 Z 的大小为 8 ,当然 A 的大小也会有相应变化。那么未优化的编译上 Y 和 Z为什么是 8 呢?那是因为:(1)继承了 X 的 1 byte (2)对 1 byte 进行内存对齐( alignment ),调整为 4 byte以和另一个指针类型的内存分布对齐。(3) 加上增加的一个额外指针(4 byte)。正好 8 bytes。那么优化后的 Y 和 Z 怎么是 4 字节呢?进行优化的编译器考虑到 derived class 既然有了一个 member(虚继承带来的指针),那就没必要按插 1 byte了, 编译器会让 empty virtual base class(此处的 X ) 的地址就是 derived class(此处的 Y 和 Z)的地址最开头部分,因此省去了那个 1 byte,也就没有所谓的 alignment 了。最后 X 和 Y的大小只有一个指针的大小(4 bytes)。如果将 Y 继承中的 virtual 关键字去掉,那么 Y 的大小就会是 1 byte---因为至此,它不像 virtual  继承有额外的 member,得按插!

  大家需要注意的一点:nonstatic data member 防止的是“个别的 class object ”感兴趣的数据。 static data member 放置的是 “整个 class”感兴趣的数据,所以 static 并不放在一个类的地址中,而是放在程序的 global data segment 。不管 class 产生(直接产生或间接派生)出多少个 object ,static data members 永远只存一份实体。甚至,没有任何 object ,其 static data members 也已存在!

 

转载于:https://www.cnblogs.com/zhuwbox/p/3424891.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值