前言
OC是面向对象语言,那我们在创建一个对象后,可以为对象赋值,储存等一系列的操作,那我们为什么可以这么操作?系统在背后偷偷的帮我们干了什么事?
创建一个对象
//创建一个对象 (alloc 为对象分配了内存 init为对象初始话)
//实事如此吗?
//Person *p = [[Person alloc]init];
Person *p = [Person alloc];
//给对象的一个属性赋值
p.age = 10;
//2020-01-14 17:35:08.450074+0800 ceshituisong[1778:1097651] 打印出age:10
NSLog(@"打印出age:%d",p.age);
从上面的测试结果看来,alloc后系统就给对象分配了内存和初始化。那么init到底做了什么吗?alloc在底层到底是怎么实现的?
分析objc4_750源码
源码下载地址
在源码中我们发现init方法什么也没有做,只是返回了自己本身。
+ (id)init {
return (id)self;
}
- (id)init {
return _objc_rootInit(self);
}
id _objc_rootInit(id obj)
{
// In practice, it will be hard to rely on this function.
// Many classes do not properly chain -init calls.
return obj;
}
在源码中我们发现alloc在系统底层调用方法的顺序是:+ (id)alloc ->id
_objc_rootAlloc(Class cls) -> static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false) ->id
class_createInstance(Class cls, size_t extraBytes) ->id
_class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone, bool cxxConstruct = true, size_t *outAllocatedSize = nil)
下面对最后一个方向进行分析,看看系统是怎样创建对象的。下面是源码,已经将不重要的代码删除。
static __attribute__((always_inline))
id _class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone, bool cxxConstruct = true, size_t *outAllocatedSize = nil)
{
//计算对象需要的内存空间
size_t size = cls->instanceSize(extraBytes);
id obj;
if (!zone && fast) {
// 进行分配内存空间
obj = (id)calloc(1, size);
if (!obj) return nil;
//进行创建对象
obj->initInstanceIsa(cls, hasCxxDtor);
}
//返回对象
return obj;
}
size_t instanceSize(size_t extraBytes) {
//字节对齐(兼容硬件 效率 iOS是8字节对齐) 空间换时间
size_t size = alignedInstanceSize() + extraBytes;
// CF requires all objects be at least 16 bytes.
if (size < 16) size = 16;
return size;
}
网友评论