空类的大小:
从名称上看,我们可能会认为空类的大小应该是
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)
。
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员