C++ 面试宝典之:空类大小究竟是不是 0?

以下内容为本人的学习笔记,如需要转载,请声明原文链接 微信公众号「ENG八戒」mp.weixin.qq.com/s/pD4bIjX2k...

首先,空类是什么?空类指的是不包含任何数据成员的类,但可能包含方法成员。

实例化时,对象需要分配存储空间用于存放数据成员,数据成员的大小和数量决定了对象的大小。如果一个类不包含任何的数据成员,那么实例化的时候应该不需要这些多余的空间。

但是实例化对象的存储空间唯一代表该对象,相应的空间地址也应该是唯一的。如果类实例化时没有分配空间,空间地址也无法确定,那么这个对象如何被识别和访问?

同一个类可以被多次实例化,也就是创建多个对象,每次实例化的对象应该是不同的,那么对应的存储空间位置也是不同的。如果地址重复说明该对象应该是同一个。

为了区分对象是否是同一个,一般通过地址来比较。下面来看看定义一个空类,分别创建两个实例对象,测试对比地址是否一致:

c 复制代码
class test { };

int main()
{
  test a, b;
  if (&a == &b)
    std::cout << "impossible: report error to compiler supplier" << std::endl;

  test* p1 = new test;
  test* p2 = new test;
  if (p1 == p2)
    std::cout << "impossible: report error to compiler supplier" << std::endl;

  return 0;
}

如果空类对象的大小为 0,那么分配的存储空间就会重叠,地址也会一样。但是上面的例程编译后实际运行结果没有输出任何信息,可见同一个空类的不同实例的地址不同,也就是说这个时候的空类的对象也会占用空间,为什么呢?

因为编译器需要区分空类的实例,所以强制给它分配了冗余的空间,这样创建空类实例返回的地址才会不一样,而且类实例化可以保留的最小内存量是 1 个字节。所以,直接实例化空类,对象大小为 0。

派生后优化

同时,如果用空类去派生新类,并且派生类存在数据成员时,派生类实例化的对象大小会受到基类的冗余空间影响吗?

ini 复制代码
class derive : public test {
  int a;
  // ...
};

int main()
{
  derive p;
  void* p1 = &p;
  void* p2 = &p.a;
  if (p1 == p2)
    std::cout << "nice: good optimizer";

  return 0;
}

编译执行上面的程序

bash 复制代码
nice: good optimizer

从输出信息来看,p.a 的地址和 p 的地址一样,可见空类 test 的派生类 derive 实例化后对象大小没有了基类对象原有的冗余空间,也就是空类这个时候真的不再占用空间。这要归功于编译器的优化处理,由于派生类存在数据成员,所以派生类实例化的对象大小会被优化,不再为基类分配冗余空间。

相关推荐
青瓦梦滋3 分钟前
WebSocket协议
linux·服务器·网络·c++·websocket·网络协议·http
CodeYp20195 小时前
第15讲:二叉搜索树
开发语言·c++·二叉搜索树
pipixia200336 小时前
C++继承面试四连问:内存叠加、私有继承、sizeof、权限重映射
c++·面试·嵌入式·继承·面向对象·对象模型
牵猫散步的鱼儿9 小时前
C++ 内存分区
c++
choumin9 小时前
C++ 标准容器为什么不能存引用
c++·容器·引用类型
谙弆悕博士9 小时前
用 C 写了个 Windows 聊天室,踩了几个多线程和控制台的坑
c语言·开发语言·c++·windows·网络编程·聊天室
stolentime10 小时前
CF2277E Tree Guessing题解
c++·算法·贪心算法·交互·ad-hoc
syagain_zsx11 小时前
ODB 与 MySQL:C++ 里的 ORM 实践(类即表、事务铁律与查询封装)
开发语言·数据库·c++·mysql·工具库·1024程序员节
小鱼仙官11 小时前
使用Qt封装C/C++ 动态库 用于第三方调用
c语言·c++·qt
晚风予卿云月12 小时前
【C++高并发内存池】 1.定长内存池的实现
开发语言·c++·内存管理