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

相关推荐
_小柏_13 分钟前
C/C++基础知识复习(18)
c语言·c++
闲人编程17 分钟前
爬虫反爬机制和解决方案
开发语言·c++·爬虫·python·验证码
xianwu54325 分钟前
【设计模式】工厂模式
开发语言·c++·设计模式·简单工厂模式·抽象工厂模式
Enoch8881 小时前
Day09 C++ 存储类
java·jvm·c++
长弓聊编程1 小时前
如何使用gtest编写C++单元测试代码
c++·单元测试
bbqz0072 小时前
KTL (0.9.2,通达信mdt文件)
c++·股票·通达信·tdx·mdt
丶Darling.2 小时前
Day39 | 动态规划 :完全背包应用 零钱兑换&&零钱兑换II
c++·算法·动态规划
Mr_Xuhhh3 小时前
递归搜索与回溯算法--递归(2)
开发语言·数据结构·c++·算法·链表·深度优先
Ni-Guvara5 小时前
对象优化及右值引用优化(四)
开发语言·c++
Ddddddd_1587 小时前
C++ | Leetcode C++题解之第560题和为K的子数组
c++·leetcode·题解