对象的内存空间
首先创建一个Person
类
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) long height;
@property (nonatomic) char c1;
@property (nonatomic) char c2;
@end
实例化一个Person
对象
Person *person = [Person alloc];
person.name = @"Cc";
person.nickName = @"cc";
person.age = 18;
person.c1 = 'a';
person.c2 = 'b';
调试对象地址的信息
16字节输出信息.png我们可以正常输出字符串对象属性的信息,但是无法找出基本数据类型信息。
调试基本数据类型信息
输出基本数据类型信息.png这是因为苹果通过属性重排使得完成了内存优化,这种内存对齐方式来源于结构体内存对齐。
结构体内存对齐
结构体对象的内存
首先创建两个结构体对象Struct1
struct Struct1 {
double a;
char b;
int c;
short d;
}struct1;
Struct2
struct Struct2 {
double a;
int b;
char c;
short d;
}struct2;
通过SizeOf
函数获取Struct1
与Struct2
的大小分别是24
和16
,那么为什么占用的内存大小不相等呢?
在探索结构体内存之前,我们需要先了解内存对齐的原则。
内存对齐的原则
-
数据成员对⻬规则
结构体或联合体的数据成员,第⼀个数据成员放在offset为0的地⽅以后每个数据成员存储的起始位置要从该成员⼤⼩或者成员的⼦成员⼤⼩的整数倍开始。
例如,
int为4字节,则要从4的整数倍地址开始存储
-
结构体作为成员
如果⼀个结构⾥有某些结构体成员,则结构体成员要从其内部最⼤元素⼤⼩的整数倍地址开始存储。
例如,
struct a⾥存有struct b,b⾥有char,int ,double等元素,那b应该从8的整数倍开始存储
-
结构体的总⼤⼩
结构体的大小必须是其内部最大成员的整数倍,不足的要补齐。
计算结构体内存的大小
根据数据类型对应的内存大小以及内存对齐的原则,计算Struct1
与Struct2
的大小。
-
计算
Struct1
的大小- 变量
double a
,字节大小8
,范围(0,7)
- 变量
char b
,字节大小1
,8为1的整数倍,则b
的位置为8
- 变量
int c
,字节大小为4
,12是4的整数倍,则c
的内存范围为(12,15)
- 变量
short d
,字节大小为2
,16是2的整数倍,则d
的内存范围为(16,17)
最终结构体的大小为最大成员
double a
的整数倍24
。 - 变量
-
继续计算
Struct2
的大小- 变量
double a
,字节大小8
,范围(0,7)
- 变量
int b
,字节大小4
,8为4的整数倍,则b
的内存范围为(8,11)
- 变量
char c
,字节大小为1
,12是1的整数倍,则c
的内存范围为(12)
- 变量
short d
,字节大小为2
,14是2的整数倍,则d
的内存范围为(14,15)
最终结构体的大小为最大成员
double a
的整数倍16
。 - 变量
属性重排
根据上述可以得出一个结论,结构体内存大小与结构体成员内存大小的顺序有关,苹果中将类中的属性进行重排,来达到优化内存的目的。
获取内存大小的三种方式
sizeof
,获取该数据类型占用空间的大小。
class_getInstanceSize
,获取实例对象中成员变量的内存大小,是采用8字节对齐
,参照的对象的属性内存大小。
malloc_size
,获取系统实际分配的内存大小,采用16字节对齐
,参照的整个对象的内存大小,对象实际分配的内存大小必须是16的整数倍。
网友评论