类占用内存大小

类也是一种数据类型,说起数据类型,最熟悉不过就是int整型数据类型、char字符数据类型、float浮点数据类型等等了

1.int整型

以int整型为例,如果问int类型占多少内存呢?大家肯定毫无犹豫的说,当然是4个字节了。不错,一个int类型数据占4个字节,在计算机上用sizeof(int)也可以检测出来。但能说int类型占4个字节吗?

系统并不会给一个类型分配内存的,只会给这个类型数据分配内存。所以说int类型占4个字节并不正确,而是int类型的数据占4个字节,那问题又来了,为什么在计算机上用sizeof(int)得到的结果又是4呢,为什么不是0呢?刚说的int类型并不占内存啊

sizeof并不是计算的int类型在计算机的内存上占有的内存,它只是计算了int类型在计算机上该占有几个字节。比如我们声明一个变量,为什么要在变量前面一定要写出这个变量是什么类型,这个类型就是在告诉计算机该给这个变量分配多少内存,如果变量是整型的,就分配4个字节;如果变量是char型的,就分配一个字节,所以,占计算机内存的并不是int这个类型,而是这个变量。类型就相当于一个模板,计算机就依照这个模板给变量分配内存了。这下应该相信说清楚了

2.结构体

在说类之前,先说说结构体,为什么呢,说类是结构体的升级也不过分,那就先认识一下结构体

C++和C在结构体上还是有着很大的不同:

1)C中不能在结构体中定义函数,当然声明也是不可以,就是结构体不能存在函数,只能存在数据类型;但在C++中,结构体是可以定义函数的,这是与C不同的地方之一

2)C中在定义一个结构体对象或者说变量的时候,必须加上struct关键字,即:

关键字struct+结构体名+对象(变量)名;例如:

struct MyStruct op;

但是在C++中,不必加上关键字,直接用结构体名+对象(变量)名即可,例如:

MyStruct op;

接下来在C++中检测结构体类型该占多少内存,但不解释,留着类中再解释,现在只看看在VS2017上的运行结果,猜猜为什么

0)一个空结构体:

#include <iostream>
#include <string>
using namespace std;

struct MyStruct
{
	
};

int main()
{
	cout << sizeof(MyStruct) << endl;
	MyStruct op;
	cout << sizeof(op) << endl;

	system("pause");
	return 0;
}

结果:

1)结构体中只声明一个int整型变量:

struct MyStruct
{
	int a;
};

结果:

2)结构体声明两个int整型变量:

struct MyStruct
{
	int a;
	int b;
};

结果:

3)一个int型和一个char型

struct MyStruct
{
	int a;
	char b;
};

结果:

4)一个int型和一个float型

struct MyStruct
{
	int a;
	float b;
};

结果:

5)一个int型一个double型

struct MyStruct
{
	int a;
	double b;
};

结果:

6)一个int型和一个具有5个元素的int型数组

struct MyStruct
{
	int a;
	int b[5];
};

 结果:

7)一个int型和一个静态int型

struct MyStruct
{
	int a;
	static int b;
};

结果:

8)一个int型和一个int指针型

struct MyStruct
{
	int a;
	int *b;
};

 结果:

9)一个int型和一个函数

struct MyStruct
{
	int a;
	void fun()
	{
	}
};

结果:

3.类

本是来解释类占有内存的大小的,结果上面解释结构体就很用了那么多篇幅,但是如果你能解释上面全部的结果,那么类的内存大小你也可以不用看了

接下来就直接解释类的内存计算方法,不再单独取例子了,也对应解释上面结构体的结果,这些结论参考了博客:类的占有内存大小自定义类所占用的内存空间,如果想具体知道原因可以参考这两篇博客,本博客只做简单的解释并不做具体的分析

1)一个空类占有1个字节。因为一个空类也要实例化,所谓类的实例化就是在内存中分配一块地址,每个实例在内存中都有独一无二的地址。同样空类也会被实例化,所以编译器会给空类隐含的添加一个字节,这样空类实例化之后就有了独一无二的地址了。所以空类的sizeof为1。这也解释了空结构体的sizeof也是1,对应了上面的0)

2)类的大小为类的非静态成员数据的类型大小之和。这说明了类的大小主要依据的是类中非静态成员数据的类型,所以只有一个int型数据的结构体占有4个字节,这对应了上面的1);有两个int型数据的结构体占8个字节,这对应上面的2);一个int型和一个float占8个字节,这对应了上面的4);一个int型和一个具有5个元素的int型数组占24字节,这对应了上面的6);一个int型和一个int型指针占8个字节,这对应了上面的8);(解释一下,不管是int型指针还是char型指针,或者double型指针,指针类型占的内存大小只跟系统有关,32位占4字节,64位占8字节)。同时这句话也说明了静态成员数据和函数并不计算在内,所以,一个int型和一个静态int型占4个字节,这对应了上面的7);一个int型和一个函数占4字节,这对应了上面的9)

3)类的内存分配还要考虑的对齐问题。一个int型和一个char型本应该是占有5个字节,怎么是8个字节呢,这是因为内存对齐更有利于内存的分配和管理,系统主动给char型添加3个字节,满足4个字节,所以一个int型和一个char型占8个字节,这对应了上面的3);一个int型和一个double型占16个字节,这对应上面的5);(解释一下为什么是16,double占8个字节,为了对齐,系统给int型添加了4个字节,如果我们在结构体中设置两个int型数据和一个double型数据,也会得到16字节)

4)虚函数由于要维护在虚函数表,所以要占据一个指针大小,也就是4字节。无论多少个虚函数,只有这一个指针,而一般的函数是没有这个指针的,而且也不占类的内存

5)子类的大小是本身成员变量的大小加上所有父类的大小。注意父类子类共享一个虚函数指针

4.静态数据成员和函数

肯定有人再问为什么静态数据成员和函数不占类和结构体中的内存呢

先说说函数,所有的函数都是放在代码区的,不管是一般函数还是成员函数,成员函数中不管是一般成员函数还是静态成员函数;而sizeof访问的程序的数据区,所以不包含函数的大小

对于静态成员数据,静态成员数据并不属于某个特定的对象,他们属于全局变量,所以也相当于不是类和结构体的成员了,所以不包含静态成员数据的大小

5.类和结构体对象的内存分配

经过自己实验发现,每个结构体对象和类对象中每个成员数据的内存分配是连续的,内存分配顺序按声明的顺序

猜你喜欢

转载自blog.csdn.net/qq_33757398/article/details/81359843