alloc & init & dealloc
在Objective-C中,alloc,init和dealloc是经常使用的函数,那么它们内部到底是如何实现的呢?通过查看libobjc运行时库,可以发现他们的工作原理。
1 alloc
alloc的功能就是为对象分配内存,关键代码如下:
if (!UseGC && !zone && fast) { obj = (id)calloc(1, size); if (!obj) return nil; obj->initInstanceIsa(cls, hasCxxDtor); }
在上面的代码中,calloc就是用来位对象分配内存的,并且calloc还会将这块内存区域初始化位0,其中的size就是对象的大小=isa指针(下面介绍) + 对象中的实例变量。为了内存对齐,size的大小可能会包含一些填充字节。分配好的内存被转换为id类型,下面是运行时库中对id类型的定义:
typedef struct objc_object *id;
可以看到,id类型其实就是一个结构体指针,该结构体为objc_object,而struct objc_object的定义为(只展示了struct里面的实例变量,去掉了struct里面的方法):
struct objc_object { private: isa_t isa; }
struct objc_object中的成员变量isa是一个指针,指向的是对象所属类的Class对象。
分配好内存之后,调用obj->initInstanceIsa方法,这个方法的作用就是用该对象所属类的Class对象地址初始化对象的isa指针,类的Class对象地址由参数cls提供。有关对象,对象所属类的Class对象的介绍,可以参看链接:刨根问底Objective-C Runtime(2)- Object & Class & Meta Class。
2 init
init方法很简单,什么也不做,简单的返回对象地址,源码如下:
- (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; }
3 dealloc
dealloc的作用就是释放内存,关键源代码如下:
id object_dispose(id obj) { if (!obj) return nil; objc_destructInstance(obj); #if SUPPORT_GC if (UseGC) { auto_zone_retain(gc_zone, obj); // gc free expects rc==1 } #endif free(obj); return nil; }
object_dispose是dealloc用来释放内存所调用的函数,可以看到,object_dispose只是简单的调用了free函数来释放内存。但是在调用free之前,object_dispose调用了objc_destructInstance。objc_destructInstance函数如下:
void *objc_destructInstance(id obj) { if (obj) { // Read all of the flags at once for performance. bool cxx = obj->hasCxxDtor(); bool assoc = !UseGC && obj->hasAssociatedObjects(); bool dealloc = !UseGC; // This order is important. if (cxx) object_cxxDestruct(obj); if (assoc) _object_remove_assocations(obj); if (dealloc) obj->clearDeallocating(); } return obj; }
其中标红色的方法会对类中包含的成员变量进行释放,这个释放动作是由编译器来保证的(ARC下),即使overwrite了某个类的dealloc,并且overwrite dealloc时没有对成员变量赋值nil,这个过程也不受影响,照样进行。
最后附上libObjc的下载连接:https://github.com/longv2go/objc4-646