不同类型数据所占字节</>
内存对齐</>
在iOS 64位系统中,采用8字节对齐(计算属性内存空间大小总和),最小内存大小为16字节,实际分配空间是16字节对齐(实际分配空间)。
对象的属性内存布局遵循下面规则
- 结构体变量的首地址是其最长基本类型成员的整数倍;
- 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如不满足,对前一个成员填充字节以满足;
- 结构体的总大小为结构体最大基本类型成员变量大小的整数倍;
- 结构体作为成员:如果一个结构体内部成员包含其他结构体成员,则结构体成员要从其内部成员最大元素大小的整数倍地址开始存储
- 结构体中的成员变量都是分配在连续的内存空间中。
- 结构体成员顺序不同,会导致所占内存空间不一样;对象经过编译器优化,就不会有这个问题
输出结果
NSObject 的一个实例对象所占内存是多少
#import <objc/runtime.h>
#import <malloc/malloc.h>
// ChildrenObject 有 age, name 属性,
// 如果对象创建了没去赋值属性,它会是内存假地址
ChildrenObject *obj = [[ChildrenObject alloc] init];
obj.age = 20;
// class_getInstanceSize依赖于<objc/runtime.h>,返回创建一个实例对象所需内存大小。就是获取对象的全部属性的大小总和,然后按8位对齐获得,不足8位补齐8位。
NSLog(@"class_getInstanceSize = %zd", class_getInstanceSize([ChildrenObject class]));
// malloc_size依赖于<malloc/malloc.h>,返回系统分配给对象的内存大小,而且最小是16字节
NSLog(@"malloc_size = %zd", malloc_size((__bridge const void *)obj));
// 在64位架构下,自定义一个NSObject对象,无论该对象生命多少个成员变量,最后 sizeOf 得到的内存大小都是8个字节, 是因为 sizeOf获取的是类型所分配内存,所传参数为指针类型,所以最后得到的都是8
NSLog(@"sizeof = %zd", sizeof(obj));
注意上面三种方法所获取结果的不同
- class_getInstance 获取实例对象在内存对齐的情况下,所占大小
- malloc_size 获取的是实际系统所分配的内存大小
- sizeOf 获取类型所占字节大小,如果传的是对象,永远都是8;如果是结构体实例获取的是
延伸
-
iOS 系统为对象实际分配内存空间为什么是16的倍数,有哪些策略
libmalloc 分析 16的倍数保证了高效存取和合理的利用率,有 tiny, small, large 策略
-
联合体,结构体,对象的异同
- 结构体和类的区别
- 结构体值类型,类是引用类型。结构体变量赋值是直接赋值,值传递;对象的赋值,是指针传递
- 结构体没有继承特性,类有
- 结构体有默认构造函数; class 需要自己构建构造函数,
- 结构体只能封装属性,类可以封装属性和方法
- 结构体变量分配在栈,OC对象分配堆;栈的空间小,访问速度快;堆空间大,访问速度慢
- 结构体和联合体的区别
- 结构体是
- 联合体是什么
- 结构体和类的区别
-
结构体里有 对象成员(NSString, eg), 对象里有结构体属性,会有什么问题
-
如果给类增加方法,类实例对象内存大小会变化么,为什么,为什么这么设计
-
创建对象的时候,并不会给对象的方法分配内存,只会给属性、成员变量分配内存
-
一个类可能创建多个实例,每个实例的方法都一样,没有差异性,完全可以抽离出来,所有对象共用这块存储方法的内存,实际上都存储在 类实例 里面了,一个类只有一个类实例,由系统创建。
-
这么设计的好处就是节省空间,加快初始化速度等
-