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 实例化后对象大小没有了基类对象原有的冗余空间,也就是空类这个时候真的不再占用空间。这要归功于编译器的优化处理,由于派生类存在数据成员,所以派生类实例化的对象大小会被优化,不再为基类分配冗余空间。

相关推荐
fpcc27 分钟前
c++23中的print和println
c++·c++23
玉树临风江流儿1 小时前
C++左值、右值、move移动函数
开发语言·c++
许长安2 小时前
c/c++ static关键字详解
c语言·c++·经验分享·笔记
Murphy_lx3 小时前
C++ thread类
开发语言·c++
月夜的风吹雨3 小时前
【C++ STL 深度剖析】:vector 底层模拟实现与核心陷阱解析
c++·vector·类和对象·visual studio
彩妙不是菜喵3 小时前
C++ 中 nullptr 的使用与实践:从陷阱到最佳实践
开发语言·jvm·c++
_dindong4 小时前
笔试强训:Week-4
数据结构·c++·笔记·学习·算法·哈希算法·散列表
liu****5 小时前
12.线程(二)
linux·开发语言·c++·1024程序员节
小冯的编程学习之路6 小时前
【C++】:C++基于微服务的即时通讯系统(2)
开发语言·c++·微服务
许长安6 小时前
C/C++中的extern关键字详解
c语言·开发语言·c++·经验分享·笔记