1. 虚函数
如果 ClassA 有虚函数, 编译器会给每个 ClassA 对象添加一个隐藏成员, 该隐藏成员保存了一个指向虚函数表的指针.
所以 sizeof ClassA 如果比你预想的多了 4 位, 不要惊奇, 因为多了一个 size(指针).
但是这个隐藏指针是先算还是后算呢?
class A
{
int a;
char b;
double c;
int d;
virtual void aa(){};
};
sizeof(A):
先算是 (4 + 4) + (1 补7) + 8 + (4 补4) = 32
后算是 (4 + 1 补3) + 8 + (4 + 4) = 24
结果是: 32.
结论就是: 隐藏指针最先计算.
2. 如果类中有类成员或有数组, 那sizeof 是怎么算的呢?
class B
{
public:
int a;
char name[7]
char c;
};
sizeof(B) 结果是: 12. (4) + (4) + (3 +1) = 12
结论就是: 数组是被分开来算的, 就好比有 7 个char name.
class C
{
public:
B b;
double d;
};
class D
{
public:
B b;
int d;
};
sizeof(C) 结果是: 24. (4+4) + (3+1 补4) + 8 = 24 还是 12 + 12 = 24呢?
sizeof(D) 结果是: 16. (4) + (4) + (3+1) + 4 = 16, 上面的结论明显是前者.
结论就是: 成员变量 b(类B 的对象), 不是被看成一个整体, 而是把所有的基本类型变量陈列起来, 一起计算.
3. 共用体 union
union U
{
char a;
int b;
double c;
};
sizeof(U) 结果是: 8.
结论就是: 共用体是看 最大的成员变量的类型 的. U中最大的就是double了.
那如果共用体U中某个成员变量的类型是某个类呢?
union U2
{
char a;
int b;
double c;
B d; //注意类B不能有自定义的构造函数,
};
sizeof(U2) 结果是: 16.
从前面可以知道sizeof(B) 结果是12, 如果是所有的基本类型变量陈列在一起, 那最大的应该是 double, 但结果并不是 8, 而是16. 如果用 8字节对齐来计算 B 占用的内存, (4+4) + (3+1补4) = 16, 跟 sizeof(U2) 的结果一样. 这也不违背上面已经取得的结论了.
结论就是: 共用体是看 最大的成员变量的类型 的, 不管该类型是基本类型, 类或结构. 如果是类或结构类型, 其字节对齐是看所有基本类型中最大的.