为什么空类大小是一

开发 前端
本文想分享的空基类优化(EBO)技术。具体其实上面的示例已经很清楚了,就是子类如果继承空类,并不会产生额外的大小,它的大小还是子类本身的大小。

[[435414]]

我们可能都知道,C++中空类的大小是1。

  1. #include <iostream> 
  2.  
  3. class EmptyA {}; 
  4.  
  5. int main() { 
  6.     std::cout << "sizeof EmptyA " << sizeof(EmptyA) << std::endl; 
  7.     return 0; 
  8. }; 

结果如下:

  1. sizeof EmptyA 1 

然而在C语言中空结构体的大小是0,空结构体大小是0我们貌似可以理解,但为什么到C++中,空类的大小却是1呢?

原因如下:

实际上,这是类结构体实例化的原因,空的类或结构体同样可以被实例化,如果定义对空的类或者结构体取sizeof()的值为0,那么该空的类或结构体实例化出很多实例时,在内存地址上就不能区分该类实例化出的实例,所以,为了实现每个实例在内存中都有一个独一无二的地址,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存得到了独一无二的地址,所以空类所占的内存大小是1个字节。

实际上,这不是本文的重点,重点其实是想向大家分享一下C++中的空基类优化(EBO)技术。

直接看代码:

  1. #include <iostream> 
  2.  
  3. class EmptyA {}; 
  4.  
  5. class A { 
  6.     int a; 
  7. }; 
  8.  
  9. class B : public EmptyA { 
  10.     int b; 
  11. }; 
  12.  
  13. class D : public A { 
  14.     int d; 
  15. }; 
  16.  
  17. class C { 
  18.     int c; 
  19.     EmptyA d; 
  20. }; 
  21.  
  22. int main() { 
  23.     std::cout << "sizeof EmptyA " << sizeof(EmptyA) << std::endl; 
  24.     std::cout << "sizeof B " << sizeof(B) << std::endl; 
  25.     std::cout << "sizeof C " << sizeof(C) << std::endl; 
  26.     std::cout << "sizeof A " << sizeof(A) << std::endl; 
  27.     std::cout << "sizeof D " << sizeof(D) << std::endl; 
  28.     return 0; 
  29. }; 

结果如下:

  1. sizeof EmptyA 1 
  2. sizeof B 4 
  3. sizeof C 8 
  4. sizeof A 4 
  5. sizeof D 8 

这里:

  • 空类EmptyA的大小是1,上面已经介绍过。
  • 类C的大小是8,因为int占四个字节,EmptyA占1个字节,再加上字节对齐,编译器补了4个字节,最后就是8。
  • 类A的大小是4,没啥毛病。
  • 类D的大小是8,因为int占4个字节,继承的A类也占4个字节,最后就是8。

可以看到,类B的大小是4。

为什么同样是继承。类D把类A的大小继承了下来。而类B的大小却是4,为什么没有把EmptyA的大小继承下来呢?

这就是本文想分享的空基类优化(EBO)技术。具体其实上面的示例已经很清楚了,就是子类如果继承空类,并不会产生额外的大小,它的大小还是子类本身的大小。

EBO技术有什么作用?

我们普通开发者可能认为多那一两个字节没什么大不了的,但是在STL中,在精益求精、寸土必争的委员会大佬们那里,这至关重要,再贴下EBO在STL中的作用。

  1. template<typename _Tp, _Tp __v> 
  2. struct integral_constant { 
  3.     static constexpr _Tp                  value = __v; 
  4.     typedef _Tp                           value_type; 
  5.     typedef integral_constant<_Tp, __v>   type; 
  6. }; 
  7.  
  8. typedef integral_constant<bool, true>     true_type; 
  9.  
  10. typedef integral_constant<bool, false>    false_type; 
  11.  
  12. template<> 
  13. struct __is_floating_point_helper<float
  14. public true_type { }; 
  15.  
  16. template<> 
  17. struct __is_floating_point_helper<double
  18. public true_type { }; 

STL中各种空类继承,如果继承空类会给子类产生额外的大小,那还了得?

我们可能平时用不到EBO技术,但还是建议了解,说不上哪天可以和面试官装一波呢。

打完收工。

 

责任编辑:武晓燕 来源: 程序喵大人
相关推荐

2020-06-02 11:25:26

Linux默认页内存

2012-08-01 14:04:46

Surface

2020-07-29 07:05:00

DevSecOps

2020-03-11 16:20:03

Serializabl接口Java

2021-06-02 10:52:01

HTTP3Linux

2020-09-15 15:53:31

边缘计算云计算5G

2023-11-07 08:00:00

Kubernetes

2018-03-22 14:47:13

容器开发人员笔记本

2024-01-23 11:31:24

模型AI

2023-12-06 12:11:43

类加载器双亲委派模型

2021-10-21 05:30:48

Data Fabric数据管理架构边缘计算

2018-01-31 14:50:04

LinuxmacOS .bashrc

2021-10-22 05:52:27

数据库调整大小容量

2020-06-18 07:16:22

联网车队物联网IOT

2018-01-02 10:14:14

CRM

2021-10-18 05:42:23

代码编码开发

2022-10-08 06:38:01

元宇宙NFT加密货币

2009-08-14 15:42:11

什么是.NET接口.NET抽象类

2024-03-11 11:02:03

Date类JavaAPI

2023-09-21 09:00:00

Merge Que开发工具Mergify
点赞
收藏

51CTO技术栈公众号