一、基本数据类型在不同编译器下占用字节数比较与总结,测试过程不详述了,直接看下表结论!
下表中右侧总结部分是依据占用字节数进行着色,同一种颜色类型的数据成员占用字节数要么一致,要么具有同样的性质,这样比较容易理解的记忆。
占用字节数
16位编译器 32位编译器 64位编译器
总结
char 1 1 1
char一直占1个字符,任何编译器都只占一个字节
char* 2 4 8
char*是指针变量,N位系统含有N个bit,即占用N/8个字节
short int 2 2 2
short int一直占2个字节
int 2 4 4
int在X86和X64都是4位,仅在16位系统是2字节
unsigned int 2 4 4
无符号int与int本身的占位一样,不区分编译器
float 4 4 8
float由于带浮点至少需要4字节,在X64编译器里面是8字节
double 8 8 8
double一直占8个字节
long 4 4 8
long 是 long int 的简写,字节长度一直等同于 float
long long 8 8 8
long long 一直占8个字节,同double
unsigned long 4 4 8
无符号long与long本身占位一样,不区分编译器
二、结构体占用字节数总结:
遵循补齐原则,以最长的数据类型作为补齐标准,最后统计有多少个补齐后的数据单元。
注意:空的结构体占用字节数为1,非空的结构体举例如下图所示:
三、类占用字节数总结:
空类和空结构体类似,都会占用一个字节;
类中的数据成员也存在补齐,与结构体中情况类似,但补齐的标准长度不仅看子类,也看父类的最大对齐长度;
静态的数据成员不占用字节;
构造函数、析构函数、成员函数都不占用字节;
对于虚函数、纯虚函数需要额外注意:
虚函数和纯虚函数都不占用字节,但会申请指针,此时占用的空间为一个指针长度;
虚函数和纯虚函数 “字节占用数” 一样;
无继承时,多个虚函数、纯虚函数共享一个指针,占用字节为一个指针长度;
有继承时,有几个父类存在虚函数就需要多少个指针,此时子类的虚函数、纯虚函数不再占用字节;
代码举例:
class A
{
};
class B
{
char ch;
virtual void func0() { }
};
class C
{
char ch1;
char ch2;
virtual void func() { }
virtual void func1() { }
};
class D: public A, public C
{
int d;
virtual void func() { }
virtual void func1() { }
};
class E: public B, public C
{
int e;
virtual void func0() { }
virtual void func1() { }
};
int main(void)
{
cout<<"A="<<sizeof(A)<<endl; //result=1
cout<<"B="<<sizeof(B)<<endl; //result=8
cout<<"C="<<sizeof(C)<<endl; //result=8
cout<<"D="<<sizeof(D)<<endl; //result=12
cout<<"E="<<sizeof(E)<<endl; //result=20
return 0;
}
四、最后分析下内存中实际数据占内存情况:
举例两个类,定义如下,Fruit 和 Apple 的内存情况分析如下:
class Fruit {
int no;
double weight;
char key;
public:
void print() { }
virtual void process() { }
};
class Apple : public Fruit {
int size;
char type;
public:
void save() { }
virtual void process() { }
};
上面两图是32位编译器环境下, Fruit(左) 和 Apple(右) 内存分布情况。
在64位编译器下,唯一的区别是 虚函数表指针从占四位变成了占八位,这和普通指针占位规律一样。
—— END ——
总结完毕,规律如上,其中的部分例子图是引用自其它文章,连接如下:
https://blog.csdn.net/jiaozhenxinaichenme/article/details/53097007
https://blog.csdn.net/hackbuteer1/article/details/7883531