本文的测试环境为VS2008。
一、成员变量的对齐问题
class A
{
short s;
};
class B
{
short s;
int i;
};
class C
{
short s;
int i;
double d;
};
class D
{
short s;
double d;
int i;
};
class E
{
D d;
short s;
};
class F
{
};
class G
{
static char c;
E e;
};
上面六个类的大小分别为
sizeof(A)=2 ,short为2字节;
sizeof(B)=8,按int的4字节对齐;
sizeof(C)=16, 按double的8字节对齐;
sizeof(D)=24,虽成员变量与C相同,但由于放的位置不同,导致大小不同,都按double的8字节对齐;
sizeof(E)=32,虽然D占24字节,但仍按8字节对齐(是因为最多按8字节对齐吗)
sizeof(F)=1,即使没有成员,编译器也会默认为之分类1字节,因为凡实例总需在内存中有地址,于是分了1字节;
sizeof(G)=32,说明char并没有占“类”的内存。因为static成员由所有类共享。
这个规律是什么呢?除了A和F,其他都是8字节对齐,是否说明是8字节对齐呢?如果不是,那为什么E会是32而不是28呢?
二、成员函数
class A
{
public:
void f1();
};
sizeof(A)=1,说明f1并没有占“类”的内存。类的成员函数在内存中只有一份。
class B
{
public:
virtual void f1();
};
sizeof(B) = 4,一个虚函数指针的大小。也就是说,类的每个实例都维护了一个虚函数指针。此虚函数指针指向一个虚函数表,借以实现多态(不在此讨论)。
class C
{
public:
static void f1();
};
sizeof(C) = 1。注意一个误区,虽然类的成员函数在内存中只有一份,但依然需要实例化这个类,方才会给函数分配内存。但static不同,即使没有实例化,static函数已经分配了内存。
三、继承
1. 非虚继承
class A
{
public:
int f1();
short s;
};
class B : public A
{
int i;
};
class C : public B
{
int f2();
virtual void f3();
};
class D : public C
{
virtual void f4();
};
sizeof(A) = 2,f1不占内存,short占2字节;
sizeof(B) = 8, short(向4字节对齐)+ int(4);
sizeof(C) = 12,short(向4字节对齐)+ int(4)+ 虚函数指针(4);// 此处说明两点,成员中若没有超过大于等于8字节的东西,就向4字节对齐。
sizeof(D) = 12,short(向4字节对齐)+ int(4)+ 虚函数指针(4);// 此处说明了即使继承了,类也只有一个虚函数指针。
2. 虚继承
首先得说,好蛋疼的虚继承!!
class A
{
virtual void aa(){};
};
class B : public virtual A
{
char j[3]; //加入一个变量是为了看清楚class中的vfptr放在什么位置
public:
virtual void bb(){};
};
class C : public virtual B
{
char i[3];
public:
virtual void cc(){};
};
sizeof(A) = 4。好理解。
sizeof(B) = 16。问题来了!
sizeof(C) = 28。
四、枚举
class A
{
public:
enum a
{
c,
d
};
};
sizeof(A) = 1。说明所有A的对象共享枚举。并且,可以直接A::c使用枚举成员,说明枚举先行于类存在于内存中。