iOS内存分配
iOS对象有3种:
- 实例对象
- 类对象
- 元类对象
对象(对象都是结构体)的内存中,包含的指针:
isa
实例对象isa---->class
类对象isa---->meta-class
superclass
主要用途:继承关系里,利用superclass寻找父类中的方法。
指向父类,跟元类指向nil。
实例对象
-
oc给一个对象分配的最小内存是16个字节。calloc函数为对象分配内存。
底层分配内存的calloc函数中,字节数判断.png
-
iOS存在内存对齐,是16的倍数。
-
生成C++文件,查看oc对象本质
clang -rewrite-objc 文件名.m -o 文件名.cpp
- 不同平台生成c++的代码不同。指定运行平台iphoneos:
iphone架构分类-->模拟器:i386、32位真机:armv7、64位真机:arm64
xrun -sdk iphoneos clang -arch -arm64 -rewrite-objc 文件名.m -o 文件名.cpp
编译后的文件可以得到
-
oc对象对应的struct结构体。比如:NSObject_IMPL
-
得到指向结构体的class指针。typeof struct objc_class *class
-
isa是指针,指针占用8个字节。int占用4个字节。
类的结构体转换:
struct className_IMPL *imp = (__bridge struct className_IMPL *)obj;
// 获得NSObject实例对象的成员变量所占用内存大小,传入类
class_getInstanceSize([NSObject class]);
// 获得point指针指向内存的大小
malloc_size((__bridge const void *)point);
// 也可用sizeof运算符计算数据类型大小,编译时即转化为数值,传入类型
sizeof(point)
ps:
- iOS内存读取是小端模式(从高地址开始读取)
大端模式,是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。
小端模式,是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。
-
内存对齐:
计算机计算占用内存大小时,内存对齐的原则三条:-
数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储。
-
结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)
-
收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的整数倍.不足的要补齐。
-
内存对齐可以提高CPU对内存数据的访问速度。
- 实例会存放在实例对象中,方法都存在于类中
- 实例对象内存中存储的信息包括:isa(所有的实例都会有的变量)、变量和值。
类对象
同一个类的实例对象,调用class方法,返回的地址值相同。
l类对象内存中存储的信息包括:isa指针、superclass指针、类属性信息、实例方法信息、协议信息、类成员变量信息(指成员变量的描述信息,并非值)。
元类对象
meta-data 描述数据的的数据,包括:类相关的描述、静态方法(类方法)信息、superclass。
元类对象和类对象结构相同,元类对象中的类对象对应信息,都是空的。