sizeof 大小计算


sizeof 大小计算

首先,sizeof是一种单目运算符,他并不是函数,在编译器就可以得到类的大小是多少。

这个里面主要的问题就是类的大小的计算过程:

  1. 首先,对于空类来说 ,sizeof 是1。因为每个类都需要在内存中有一个唯一的标识,所以他必须需要占用一定的大小。并且cpp标准里面规定了,sizeof的结果必须是非0值。

  2. 其次就是重叠对象的问题。如果这个空对象作为一个类的成员,那么他就是char一样,需要占用一定的内存

    1.  #include <iostream>
      
       struct Empty {};
      
       struct ContainsEmpty {
           Empty e;
           int i;
       };
      
       int main() {
           std::cout << "sizeof(Empty): " << sizeof(Empty) << std::endl;
           std::cout << "sizeof(int): " << sizeof(int) << std::endl;
           std::cout << "sizeof(ContainsEmpty): " << sizeof(ContainsEmpty) << std::endl;
           return 0;
       }
       
      2. ```cpp
          sizeof(Empty): 1
          sizeof(int): 4
          sizeof(ContainsEmpty): 8
  3. 如果是空类被继承的话,这个时候计算的就会忽略父类的大小

    1.  #include <iostream>
      
       struct Empty {};
      
       struct ContainsEmpty:public Empty {
           int i;
           // Empty e;
       };
      
       int main() {
           std::cout << "sizeof(Empty): " << sizeof(Empty) << std::endl;
           std::cout << "sizeof(int): " << sizeof(int) << std::endl;
           std::cout << "sizeof(ContainsEmpty): " << sizeof(ContainsEmpty) << std::endl;
      
           return 0;
       }
       
      
      ```cpp
      sizeof(Empty): 1
      sizeof(int): 4
      sizeof(ContainsEmpty): 4
  4. 然后就是普通类的计算法则

    1. 类的大小必须要是类中成员最大值的整数倍。这个主要考虑的点是数组的情况,比如在数组情况下,我们申请了多个相邻的对象,如果没有添加补充,不是成员最大值的整数倍,那么在数组情况下最终还是会发生偏移。

      1. 这片文章里面详细说明了
    2. 每个成员的起始地址都要是自己的整数倍才可以。这个比较容易理解,主要是内存对其的好处,不会跨cache line访问。

    3. 有了这两个规则,普通的,平凡类型的类我们就可以计算了。

  5. 接下来就是包含虚函数的问题了

    1. 虚函数的实现,需要虚函数指针。64位下占用8字节。每个基类都要占用一个。
    2. 他是一层一层叠的,按照书写的顺序,第一个类的虚函数指针,然后第一个类的成员。注意对齐。然后是第二各类的虚函数指针,然后是第二各类的数据成员
    3. 这个时候也就需要遵守普通的类的规范,也就是说要各种对齐
  6. 最后也就是虚基类的事情了

    1. 虚基类是解决菱形继承的问题

    2. 他的数据成员的布局是这样的,首先是普通基类的数据布局,普通基类的数据成员按照上面说的逐个排列。

    3. 在最后的地方,存放虚基类。然后问题就是我们怎么找到虚基类。无论是我们的子类,还是说上层的基类,都需要相应的索引找到对应的虚基类。

    4. 在数据成员开始的地方,我们需要一个虚基址表,用于这个类去找到虚基类的数据。这个虚表就是,他的作用就是方便对象去寻找自己的虚基类成员。

    5. 这里还会有一些拓展,就是说如果伴随着虚基类,这个可能会更加复杂。

      1. 如果主基类里面也有虚函数,那么第一个虚指针会服用。
      2. 随后就是按照场里,每个基类都有一个虚指针
      3. 如果虚基类里面也有虚函数,那么在虚基类上面也会有虚指针。


文章作者: 张兵帅
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 张兵帅 !
  目录