1.对象简介
OC对象是基于C/C++的结构体实现的,可以用以下命令把OC文件转换成CPP文件,这样可以看到OC对象的结构体样式
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc OC源文件 -o 输出的CPP文件
以下都是基于64位环境
//OC样式的
@interface NSObject{
//实际上隐藏着一个指针
Class isa;//指针8字节
}
@end
//结构体样式的
struct NSObject_IMPL{
Class isa;//指针8字节
}
//Class实际上是一个结构体指针
typedef struct objc_class *Class;
从这里可以看到,isa指针的地址其实就是指向初始化实例对象的指针的地址,类似于数组第一个元素的地址实际上就是整个数组的地址。
2.对象内存分布
1.一个isa指针占用8个字节,理论上说没有成员变量的对象应该就是8个字节,但是它底层有个限制,一个对象如果小于16字节,便让该对象等于16字节。
2.如果添加一个int类型的成员变量呢
//OC样式的
@interface NSObject{
@public
//实际上隐藏着一个指针
Class isa;//指针8字节
int _no;//4字节
}
@end
//结构体样式的
struct NSObject_IMPL{
Class isa;//指针8字节
int _no;//4字节
}
这么看应该是12字节,其实应该还是16字节,分配的16字节那个isa指针只用了8字节,还有8字节空着呢。
3.如果继承了某个类呢
/*NSObject*/
//OC样式的
@interface NSObject{
@public
//实际上隐藏着一个指针
Class isa;//指针8字节
}
@end
//结构体样式的
struct NSObject_IMPL{
Class isa;//指针8字节
}
/*------------------------------Person------------------------------------*/
//OC样式的
@interface Person{
int _age;//4字节
}
@end
//结构体样式的
struct Person_IMPL{
strcut NSObject_IMPL NSObject_IVARS;//16字节
int _age;//4字节
}
/*------------------------------Student------------------------------------*/
//OC样式的
@interface Student{
int _no;//4字节
}
@end
//结构体样式的
struct Student_IMPL{
strcut Person_IMPL Person_IVARS;
int _no;//4字节
}
其实Student与Person的内存都是16字节,首先一个空对象分配有16字节,isa占8字节,在Person中的age占4字节,还没有占完,在Student中的no占4字节,正好占完整个16字节。
有点类似于这样
//OC样式的
@interface Student{
Class isa;//指针8字节
int _age;//4字节
int _no;//4字节
}
@end
//结构体样式的
struct Student_IMPL{
Class isa;//指针8字节
int _age;//4字节
int _no;//4字节
}
4.查看内存
创建一个实例对象至少需要多少内存(是根据结构体内存对齐之后的大小)
#import <objc/runtime.h>
class_getInstanceSize([NSObject class]);
创建一个实例对象实际上分配了多少内存(是根据内存块对齐分配的,底层有个Buckets sized{16,32,48,64,80,96,112....},会根据结构体对齐之后的内存分配一个合适的16的倍数的内存块)
#import <malloc/malloc.h>
malloc_size((__bridge const void *)obj);
关于这两个的区别,例如
//OC样式的
@interface Student{
Class isa;//指针8字节
int _age;//4字节
int _no;//4字节
int _name;//4字节
}
@end
//结构体样式的
struct Student_IMPL{
Class isa;//指针8字节
int _age;//4字节
int _no;//4字节
int _name;//4字节
}//结构体内存对齐之后需要24字节
这里class_getInstanceSize的结果是24,但是它不是16的倍数,所以malloc_size是32