OC对象的本质
我们平时编写的oc代码、底层实现其实是C\C++代码
OC代码 ——> C\C++ ——> 汇编语言 ——> 机器语言
那么OC代码转换成C\C++是什么样子呢?
将OC代码转换成C\C++代码:
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc 源文件 -o 输出文件
源文件:例如 main.m 输出文件:例如 main.cpp
举例:
@interface KSPerson : NSObject
{
int_age;
int_no;
}
@end
在 main.m 中
KSPerson* per = [[KSPerson alloc] init];
然后用上边的生成C++代码如下:
struct NSObject_IMPL {
Class isa;
};
struct KSPerson_IMPL {
struct NSObject_IMPL NSObject_IVARS;
int _age;
int_no;
};
由此可见,对象的本质是sturct结构体。
创建一个实例对象,至少需要多少内存? 8
#import <objc/runtime.h>
class_getInstanceSize([NSObject class]);
创建一个实例对象,堆空间实际上分配了多少内存 ? 16
#import <malloc/malloc.h>
malloc_size((__bridge const void *)obj);
为什么实际分配的内存大于所需要的内存呢,因为计算机存在内存对齐的原则。从源码可以看出:
size_tinstanceSize(size_textraBytes) {
size_tsize =alignedInstanceSize() + extraBytes;
// CF requires all objects be at least 16 bytes.
if(size <16) size =16;
returnsize;
}
一个对象的大小小于16的时候,默认size = 16。且实际分配的内存大小总是16的倍数。
struct objc_class的结构:
struct objc_class : objc_object {
Class isa;
Class superclass;
cache_tcache; //方法缓存
class_data_bits_t bits; //用于获取具体的类信息
}
具体的调用代码:
class_rw_t* data() {
return (class_rw_t *)(bits & FAST_DATA_MASK);
}
bits & FAST_DATA_MASK 得到 :
struct class_rw_t {
// Be warned that Symbolication knows the layout of this structure.
uint32_t flags;
uint32_t version;
const class_ro_t *ro; //指向只读的结构体、存放类的初始化信息
method_array_t methods; //方法列表 (二维数组)
property_array_t properties; //属性列表
protocol_array_t protocols; //协议列表
Class firstSubclass;
Class nextSiblingClass;
char *demangledName;
}
class_ro_t 中包含的主要内容:
struct class_ro_t {
uint32_t flags;
uint32_t instanceStart;
uint32_t instanceSize; //instance对象占用的内存空间
#ifdef __LP64__
uint32_t reserved;
#endif
const uint8_t * ivarLayout;
constchar*name; //类名
method_list_t * baseMethodList; //方法列表 一维数组【method_t,method_t,...】
protocol_list_t * baseProtocols; //协议列表
constivar_list_t*ivars; //成员变量列表
const uint8_t * weakIvarLayout;
property_list_t *baseProperties;
method_list_t *baseMethods() const {
return baseMethodList;
}
};