空白基类优化(EBO,Empty Base Optimization)
空类的定义:
一个直接或间接都不包括非静态数据成员的类。(间接不包括是指所继承的基类也不含有非静态数据成员)
例如以下的类S和类A都是空类。
class S
{
S();
~S();
};
class A
{
static int x;
};
空类的大小:
从名称上看,我们可能会认为空类的大小应该是0,但是一个空类也可以定义一个对象,而每一个对象必须要有一个唯一的内存地址,所以空类的大小不为0,编译器一般将空类的大小看做一个字节。所以sizeof(S) == sizeof(A) == 1。
虽然S含有非虚成员函数,但是在c++里,一个对象里的成员函数并不表示为一个指向函数的指针,所以无论S中含有多少非虚成员函数,都不会影响S的大小。
虽然A含有静态数据成员,但是在c++里,静态成员被单独存储在全局区(静态区),所以它同样不影响A的大小。
含有虚函数的类:
例:
class D
{
virtual ~D();
};
class G
{
public:
virtual f();
};
class H : public D
{
};
sizeof(H) == sizeof(D) == sizeof(G) == sizeof(void *)
当一个类含有虚成员函数或者继承一个含有虚函数成员的类,则会给该类间接引入一个数据成员,该数据成员即为指向虚函数表的指针(vptr)。所以D和G的大小为sizeof(void *),指针的大小一般为4个字节。
空白基类优化:
例:
class T : public S
{
int x;
};
按理来说,sizeof(T) == sizeof(S) + sizeof(int),在32位的系统上,结果是5,再加上内存齐位的要求,编译器会将T的大小增大为8,但实际上sizeof(T) == 4,这就是空白基类优化:在空基类被继承后,由于空基类没有任何数据成员,所以让其在子类的对象布局中优化掉空基类所占用的一个字节。
例:
class S2 : public D {};
class T2 : public D
{
public:
virtual func();
};
sizeof(S2) == sizeof(D) == 4,sizeof(T2) == sizeof(D) == 4。
由于D含有虚函数,所以不是空类,可以看出由于S2本身是空类,在计算尺寸时,S2本身的大小(1个字节)也被优化掉了(注:如果S2不继承与其他类,则S2的大小为1个字节)。因此,EBO不仅适用于空基类,也适用于空的继承子类。
虽然T2在D的基础上又增加了一个虚成员函数,但不会因此再增加一个虚表指针,实际上,只是把从D继承而来的虚表指针赋予了一个不同的值(指向属于T2的虚函数表,因为每个含有虚函数或继承了虚函数的类都含有自己的虚函数表)。所以sizeof(T2) == sizeof(D)。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/17014649/viewspace-609058/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/17014649/viewspace-609058/