C/C++中类的存储方式
一、简单对象的存储
1、 基本类型对齐原则:
Char 1
Short 2
Int 4
Long 4
Float 4
Double 8
2、 结构体类型对齐原则:
以最大成员类型的对齐方式为准,即当需要增长时,增长最大成员类型所占用的字节数。
3、 静态成员变量不占用类对象的存储空间原则:
静态成员变量所有的类对象共享一份,在静态区域中,并不占用类对象的空间。
4、 没有任何成员变量的类对象占用一个字节的空间
验证程序:vc.net2003下运行结果
#include <iostream>
using namespace std;
/*没有任何数据成员的对象类占用一个字节的空间*/
class A1
{
};
/*静态数据成员不占用类对象的存储空间*/
class A2
{
char c1;
static int count;
};
/*当只有char类型时,以1个字节为单位对齐*/
class B1
{
char c1;
char c2;
};
/*与A比较发现,当最大为short时,以2个字节为单位对齐*/
class B2
{
char c1;
short s;
};
/*与A比较发现,当最大为int时,以4个字节为单位对齐*/
class B3
{
char c1;
int i;
};
/*与A比较发现,当最大为double时,以8个字节为单位对齐*/
class B4
{
char c1;
float d;
};
/*与A比较发现,当最大为double时,以8个字节为单位对齐*/
class B5
{
char c1;
double d;
};
/*c s i 占4个字节,d占4个字节*/
class C1
{
char c;
short s;
int i;
double d;
};
/*d占4个字节,c s i 占4个字节*/
class C2
{
double d;
char c;
short s;
int i;
};
/*c占1个字节,d从下一个4字节开始占4个字节,s i在下一个4字节中*/
class C3
{
char c;
double d;
short s;
int i;
};
/*c s 在头4个字节中,d占下四个字节,i 在最后4个字节中*/
class C4
{
char c;
short s;
double d;
int i;
};
int main()
{
cout << "size of A1 : " << sizeof(A1) << endl; /*1字节*/
cout << "size of A2 : " << sizeof(A2) << endl; /*1字节*/
cout << endl;
cout << "size of B1 : " << sizeof(B1) << endl; /*2字节*/
cout << "size of B2 : " << sizeof(B2) << endl; /*4字节*/
cout << "size of B3 : " << sizeof(B3) << endl; /*3字节*/
cout << "size of B4 : " << sizeof(B4) << endl; /*8字节*/
cout << "size of B5 : " << sizeof(B5) << endl; /*8字节*/
cout << endl;
cout << "size of C1 : " << sizeof(C1) << endl; /*16字节*/
cout << "size of C2 : " << sizeof(C2) << endl; /*16字节*/
cout << "size of C3 : " << sizeof(C3) << endl; /*24字节*/
cout << "size of C4 : " << sizeof(C4) << endl; /*24字节*/
system("pause");
return 0;
}
二、继承下的对象存储
1、虚表指针占用4个字节原则
对于一个类而言,在不存在虚函数的情况下,类的大小等于成员大小之和(按照对其原则),当存在虚拟函数时,由于要保存虚表指针,故多占用4个字节。
2、子类共享父类的虚表指针原则
在普通继承下,子类与父类共享一个虚表,子类不需要另外添加内存。
3、虚基类表指针占用4字节原则
在虚继承的情况下,继承了多个继承了同一个父类的中间类的子类只保存了一个同他基类的备份,但每个中间类都需要需要保存指向基类表的指针来指向共同的基类。
#include <iostream>
using namespace std;
class A1
{
int numA1;
};
/*与A1比较,存在虚函数的情况下,需要保存虚函数表指针占4个字节*/
class A2
{
int numA2;
virtual FunA2();
};
/*与A2比较,当不存在不同于父类的虚函数时,子类与父类共享保存虚函数表的指针*/
class B1 : A2
{
int numB1;
};
/*与A2比较,当存在不同于父类的虚函数时,子类与父类共享保存虚函数表的指针*/
class B2 : A2
{
int numB2;
virtual FunB2();
};
/*与B1比较,虚继承需要保存指向虚基类表的指针占4个字节*/
class B3 : virtual A2
{
int numB3;
};
/*虚继承下,若子类中有不同于父类的虚函数,则需要不同于父类的指向虚函数表的指针*/
class B4 : virtual A2
{
int numB4;
virtual FunB4();
};
/*虚继承下,共同的基类只有一个备份,但每个虚继承的类中多了一个只想那个虚基类表的指针*/
class C1 : B3, B4
{
int numC1;
};
void main()
{
cout << "sizeof A1 is : " << sizeof(A1) << endl; /* 4 */
cout << "sizeof A2 is : " << sizeof(A2) << endl; /* 8 */
cout << endl;
cout << "sizeof B1 is : " << sizeof(B1) << endl; /* 12 */
cout << "sizeof B2 is : " << sizeof(B2) << endl; /* 12 */
cout << "sizeof B3 is : " << sizeof(B3) << endl; /* 16 */
cout << "sizeof B4 is : " << sizeof(B4) << endl; /* 20 */
cout << endl;
cout << "sizeof C1 is : " << sizeof(C1) << endl; /* 32 */
system("pause");
}
C的内存分布:
B3指向虚基类表的指针 4
B3自己的存储区域 4
B4自己的指向虚函数表的指针 4
B4指向虚基类表的指针 4
B4自己的存储区域 4
C1自己的存储区域 4
基类的存储区域 8