zoukankan      html  css  js  c++  java
  • 一个类到底有多大?

    我们知道一个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 也已存在!

  • 相关阅读:
    vs里替换的正则表达式引用
    javascript学习
    filter用法(使静态页面和js通过iis的asp.net过滤器)
    表格的交替选择行【jquery中siblings的用法】
    表格的cell固定宽度,当内容达到宽度时换行
    collection模块(具名元组、队列、有序字典、默认值字典)、time 模块、随机模块:random、os模块、sys模块、序列化模块
    继承的用法、属性的查找顺序、组合、新式类与经典类、菱形继承等
    多态、以及常用的关于类的方法(isinstance、issubclass、slots等)运算符重载的实现、上下文管理等
    封装、prorerty装饰器、python实现封装的原理等
    面向对象、类和对象、__dict__方法、__init__方法、对象绑定方法、类绑定方法、对象交互
  • 原文地址:https://www.cnblogs.com/zhuwbox/p/3424891.html
Copyright © 2011-2022 走看看