前言
iOS开发中,我们称万物皆对象,对象的本质又是什么呢?项目开发中我们也常常说到内存的分配,程序又是如何为我们的代码创建的对象去分配内存的呢?下面我们去探索这些疑问。
正文
1、首先创建一个项目并创建一个对象。为了方便直接在main函数里面测试。
2、使用终端命令 cd到main.m文件所在目录
3、输入终端命令:
这里需要注意: :Xcode 工具,: 平台 :iOS平台, : 基于什么架构 苹果手机是基于arm64的, :重写oc文件,:输出到那个文件,文件名自定义
经过操作,我们会发现main.m文件目录下会多了一个main.cpp的c++文件,打开文件我们可以清晰的看到oc代码底层代码的实现
通过底层代码不难发现对象的本质是,那么决定一个对象在程序中占有多少内存是由这个结构体决定。
为了方便下面的探索,我们先了解下常见基本数据类型在内存占用的空间大小,以及另外一个概念。内存对齐是一种提高内存访问速度的策略,CPU在访问未对齐的内存需要经过两次的内存访问,而对齐后一次就可以了。内存对齐需要遵循以下原则:
(1)结构(struct)(或联合(union))的数据成员,第⼀个数据成员放在offset为0的地⽅,以后每个数据成员存储的起始位置需从该成员⼤⼩或者成员的⼦成员⼤⼩(如果该成员有⼦成员,例如数组,结构体等)的整数倍开始(⽐如int为4字节,所以要从4的整数倍地址开始存储;
(2)若⼀个结构⾥有某些结构体成员,则结构体成员要从其内部最⼤元素⼤⼩的整数倍地址开始存储;
(3)结构体的总⼤⼩,也就是sizeof的结果,必须是其内部最⼤成员的整数倍,不⾜的需要补⻬。
下面我们先研究一个案例,分别计算struct1、struct2、struct1占用内存大小
为什么struct1和struct2的只是变量的顺序有差异,而占用内存不一样呢,这三个结构体的占用内存是怎么计算出来的呢?
首先分析struct1,a、b、c、d依次占8字节、1字节、4字节、2字节。那struct1占用的内存大小不是a、b、c、d之和呢。struct1变量中占用空间最大的是a占8字节,那么struct1占用的空间肯定是8的整数倍。如果a占用的内存地址是从0~7,b从第8位开始,b又占1字节且1能被8整除,那么b的内存地址第8位,c从第9位开始,c占4字节但是4不能被9整除,根据内存对齐原则,9后面第12位可被4整除,所以c的内存地址是12~15,d占2字节且从16位开始,2能被16整除,所以d的内存地址是从16~17,所以struct1内部变量地址是从0~17共18个字节,根据内存对齐原则struct1需补齐6个字节总共占24个字节。
同理struct2中a、b、c、d内存地址依次为0~7、8~11、12、14~15,struct2内部变量地址是从0~15共16个字节,16刚好是8的整数倍,struct2共占16个字节。
struct3是内部嵌套了一个结构体。同上a、b、c、d的内存地址是从0~15位,在e内存是从16位开始,struct1内部最⼤元素的大小是8字节,需要从8的整数倍位置开始存储,e地址为16~33 共34字节根据内存对齐原则需补齐6字节,struct2共占40字节。