面试题:C++中void类型占几个字节的内存,空类呢?
C++的设计者们不允许类的大小为0,其原因很多。比如它们构成数组,其大小必然也是0,这会导致指针运算中普遍使用的性质失效。例如,假设类型ZeroSizedT
的大小为0,下面的操作会出现错误:
ZeroSizedT z[10];
…
&z[i] - &z[j]; //计算两个指针或地址之间的距离
通常而言,示例中的差值,一般用两个地址之间的字节数除以类型大小得到,而类型大小为0就不妙了。
虽然不能存在“类型”大小为0的类,但这扇门也没彻底关死。C++标准规定,当空类作为基类时,只要不会与同一类型的另个一个对象或子对象分配在同一地址(类内没有任何其他成员),就不需要为其分配任何空间。这称之为,空基类优化(empty base class optimization, EBCO)技术。
#include <vector>
#include <iostream>
class EmptyClass {
typedef int I; // typedef 并不会使得类成为非空
};
class EmptyClass1: public EmptyClass {
};
int main() {
std::cout << sizeof(EmptyClass) << std::endl;
std::cout << sizeof(EmptyClass1) << std::endl;
return 0;
}
运行结果如下:
如果编译器支持空基类优化,则上述结果相同,均不为0,为1(或4?可能与编译器相关)。也就是说,类EmptyClass1中的类EmptyClass并没有分配空间,其分配内存布局如下图所示:
而不支持EBCO技术的编译器上的内存布局则如下所示:
让我们再看一个例子:
#include <vector>
#include <iostream>
class EmptyClass {
typedef int I;
};
class EmptyClass1{
EmptyClass A; //子类分配在同一地址且类内没有任何其他成员
//EmptyClass B;
//int a;
};
int main() {
std::cout << sizeof(EmptyClass) << std::endl;
std::cout << sizeof(EmptyClass1) << std::endl;
return 0;
}
此时输出结果仍然为1 1。因为此时仍然满足空基类优化的条件,空基类后与子类分配在同一地址且类内没有任何其他成员。若将int i的注释去掉,则输出结果为1 8,此时空基类优化失效。