关于类所占空间:
空类占一字节,如果有虚函数会出现一个虚函数表指针空间,但是无论多少个虚函数甚至派生类都是用这一张表
64位x64虚函数指针占8字节,32位x86占4字节,上面那道题#pragma pack(2)改成了2对齐
在x64下
这个类里有double所以会变成8对齐,这个对齐也影响虚函数指针,虚函数的字节对齐也会影响整个类
class A
{
public:
int a; 4字节但是8对齐所以占8字节
double d; 8字节
A(){}
virtual ~A(){} 虚表指针x64下8字节,不管有多少个虚函数都用这一个虚表
virtual void Fun1() {}
virtual void Fun2() {}
virtual void Fun3() {}
};
sizeof(A) 在x64下== 24
class B
{
int f; 原本是4在虚函数影响下对齐成8
virtual void Fun4() {} x64下8字节
};
sizeof(B) 在x64下 == 16
但是要注意这个对齐不是说那个空间就不用了,如果还能使用就会用那一块比如
class B
{
int f; 8对齐但是两个四字节的int所以这两个int共占4字节
int g;
virtual void Fun4() {} x64下8字节
};
sizeof(B) 在x64下依旧 == 16
还要注意一旦这个类的对齐确定了,子类也受影响
class C : A
{
int a; 4对齐成8
virtual void Fun4() {} 共用不占空间
};
sizeof(B) 在x64下 = 16+8 = 32 当然这里再加一个int也是32,也可以发现C类中的int是不能和A类中的int合并一个8位的
但是如果double换成int在x86下就是12(虚表指针4 两个int 4 + 4),在x64下就是16(虚表指针8,两个int 4 + 4)
子类的内存大小等于父类的内存大小加上子类独有成员变量的内存大小
class B : A 因为A是8对齐所以B也是8对齐
{
int f; 4对齐成8
virtual void Fun4() {} 还用那个表不占内存
};
sizeof(A) == 32
在x86下
class A 这个类里有double所以会变成8对齐,这个对齐也影响虚函数指针,虚函数的字节对齐也会影响整个类
{
public:
int a; 4字节但是8对齐所以占8字节
double d; 8字节
A(){}
virtual ~A(){} 虚表指针x86下4字节,对齐成8字节
virtual void Fun1() {}
virtual void Fun2() {}
virtual void Fun3() {}
};
sizeof(A) 在x86下== 24
class B 发现4字节对齐
{
int f; 4字节
int g; 4字节
virtual void Fun4() {} x86下4字节
};
sizeof(B) 在x86下== 12
class C : A A是8对齐导致C也是8对齐
{
int a; 两个int合并占8字节
int b;
virtual void Fun4() {} 共用不占字节
};
sizeof(C) 在x86下== 24 + 8 = 32
关于为什么空类占1字节但是加一个int进去后是4字节不是5字节呢
空类可以创造对象所以它不能没有地址,当类中有成员变量后成员变量就是从这个地址开始存储的,所以类的那一个字节被覆盖掉了