我以为我会写一些关于此的文章,因为在论坛中经常会问它一个问题。
首先,这是一个C ++问题,创建没有成员的类严格违反C的规则。 这是有道理的,因为没有数据成员和虚拟函数的结构或类的唯一真正用途是作为派生其他类和结构的基础,或作为非虚拟方法的容器。
发生这种情况的原因归结为正确实施该标准,C ++标准说的一件事是“任何对象在内存中的地址都不得与任何其他变量相同”。 这样做有一个很好的理由,取一个T类型的数组,然后从另一个数组中减去指向该数组中1个条目的指针,应该得出索引的差值
T array[5];
int diff = &array[3] - &array[2];
// diff = 1
这实际上是指针算法,我们采用了2个指针,发现它们之间的区别。
编译器使用与此等效的公式来执行此计算
diff =((char *)&array [3]-(char *)&array [2])/ sizeof T;
这只是一个例子,但是这种依赖于sizeof T的计算发生在各种指针算术中。
如果由于对象的类型大小为0而允许它们具有相同的地址,则此计算将无法进行,因为
&array[3] - &array[2] = &array[3] - &array[1]
= &array[3] - &array[1]
= &array[3] - &array[0]
= 0
在指针算术中不可能区分不同的对象。
另外,存在一个问题,即编译器必须除以sizeof T,这将是除以零错误,尽管这可以进行编码。
允许对象具有相同的内存地址将导致需要实现一些相当复杂的代码来处理它们的指针算术。
因此,对象不能具有相同的内存地址,也就是说,它们必须是可单独寻址的。 最简单的方法来确保这一点? 确保所有类型的大小都为非零。 为了实现这一点,编译器向没有数据成员和虚拟函数的结构和类中添加了一个虚拟字节,以使它们的大小为1而不是0,然后保证它们具有唯一的内存地址。
From: https://bytes.com/topic/c/insights/660463-sizeof-empty-class-structure-1-a