iOS NSObject源代码(1)alloc和init
来源:互联网 发布:log4net数据库 编辑:程序博客网 时间:2024/06/07 07:28
OC对象有四种状态:
(1)创建并持有对象:alloc init
(2)持有对象:retain、copy
(3)释放对象:release
(4)废弃对象:dealloc
1. alloc
<span style="font-size:12px;">+ (id)alloc { return _objc_rootAlloc(self);}</span>
<span style="font-size:12px;">// Base class implementation of +alloc. cls is not nil.// Calls [cls allocWithZone:nil].id _objc_rootAlloc(Class cls){ return callAlloc(cls, false/*checkNil*/, true/*allocWithZone*/);}</span>
callAlloc的三个参数意思分别是cls:类信息(如NSString),checkNil:是否检查cls,allocWithZone:是否使用NSZone,如果直接调用alloc的话,系统会在默认的NSZone里面分配内存。
我们再来看看callAlloc的实现:
<span style="font-size:12px;">// Call [cls alloc] or [cls allocWithZone:nil], with appropriate // shortcutting optimizations.static ALWAYS_INLINE id callAlloc(Class cls, bool checkNil, bool allocWithZone=false){ if (checkNil && !cls) return nil;#if __OBJC2__ if (! cls->ISA()->hasCustomAWZ()) { // No alloc/allocWithZone implementation. Go straight to the allocator. // fixme store hasCustomAWZ in the non-meta class and // add it to canAllocFast's summary if (cls->canAllocFast()) { // No ctors, raw isa, etc. Go straight to the metal. bool dtor = cls->hasCxxDtor(); id obj = (id)calloc(1, cls->bits.fastInstanceSize()); if (!obj) return callBadAllocHandler(cls); obj->initInstanceIsa(cls, dtor); return obj; } else { // Has ctor or raw isa or something. Use the slower path. id obj = class_createInstance(cls, 0); if (!obj) return callBadAllocHandler(cls); return obj; } }#endif // No shortcuts available. if (allocWithZone) return [cls allocWithZone:nil]; return [cls alloc];}</span>首先先看看cls->ISA()->hasCustomAWZ(),源码在这
<span style="font-size:12px;">bool hasDefaultAWZ( ) { return data()->flags & RW_HAS_DEFAULT_AWZ; }</span>
RW_HAS_DEFAULT_AWZ 这个是用来标示当前的class或者是superclass是否有默认的alloc/allocWithZone。
所以这里hasDefaultAWZ( )方法是用来判断当前class是否有默认的allocWithZone。如果cls->ISA()->hasCustomAWZ()返回YES,意味着有默认的allocWithZone方法,那么就直接对class进行allocWithZone,申请内存空间。
if (! cls->ISA()->hasCustomAWZ()) {
if (cls->canAllocFast()){
这里这个类是否写好了快速分配的信息,因为跟allocWithZone同样调用了acalloc分配内存,不同的是后面的参数,所以个人感觉这里配置好分配内存的信息不用在后面计算。
} else {
这里和allocWithZone里面的调用方法差不多
}
}
先看看 [cls allocWithZone:zone] 这个吧
<span style="font-size:12px;">// Replaced by ObjectAlloc+ (id)allocWithZone:(struct _NSZone *)zone { return _objc_rootAllocWithZone(self, (malloc_zone_t *)zone) }id _objc_rootAllocWithZone(Class cls, malloc_zone_t *zone){ id obj;#if __OBJC2__ // allocWithZone under __OBJC2__ ignores the zone parameter (void)zone; obj = class_createInstance(cls, 0);#else if (!zone || UseGC) { obj = class_createInstance(cls, 0); } else { obj = class_createInstanceFromZone(cls, 0, zone); }#endif if (!obj) obj = callBadAllocHandler(cls); return obj;}</span>
<span style="font-size:12px;">// 抛出异常static id defaultBadAllocHandler(Class cls){ _objc_fatal("attempt to allocate object of class '%s' failed", cls->nameForLogging());}static id(*badAllocHandler)(Class) = &defaultBadAllocHandler;static id callBadAllocHandler(Class cls){ // fixme add re-entrancy protection in case allocation fails inside handler return (*badAllocHandler)(cls);}void _objc_setBadAllocHandler(id(*newHandler)(Class)){ badAllocHandler = newHandler;}</span>
可以看到#if __OBJC2__里面,iOS已经把NSZone区域给忽略了,所以NSZone内存分配方式已经不适用,之后我们再讨论iOS用哪种方式代替了。
创建OC对象都是用class_createInstance方法。
参考别人的资料,class_createInstance里面调用的class_createInstanceFromZone 点击打开链接
<span style="font-size:12px;">static __attribute__((always_inline)) id _class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone, bool cxxConstruct = true, size_t *outAllocatedSize = nil){ if (!cls) return nil; assert(cls->isRealized()); // Read class's info bits all at once for performance bool hasCxxCtor = cls->hasCxxCtor(); bool hasCxxDtor = cls->hasCxxDtor(); bool fast = cls->canAllocIndexed(); size_t size = cls->instanceSize(extraBytes); if (outAllocatedSize) *outAllocatedSize = size; id obj; if (!UseGC && !zone && fast) { obj = (id)calloc(1, size); if (!obj) return nil; obj->initInstanceIsa(cls, hasCxxDtor); } else {#if SUPPORT_GC if (UseGC) { obj = (id)auto_zone_allocate_object(gc_zone, size, AUTO_OBJECT_SCANNED, 0, 1); } else #endif if (zone) { obj = (id)malloc_zone_calloc ((malloc_zone_t *)zone, 1, size); } else { obj = (id)calloc(1, size); } if (!obj) return nil; // Use non-indexed isa on the assumption that they might be // doing something weird with the zone or RR. obj->initIsa(cls); } if (cxxConstruct && hasCxxCtor) { obj = _objc_constructOrFree(obj, cls); } return obj;}</span>calloc( )函数会默认的把申请出来的空间初始化为0或者nil。
其中 垃圾回收器GC 也会使用gc_zone,个人猜测OC已经废弃了这个用法(和NSZone一样)
2.init
init的代码相对简单,只是需要返回self就可以了
<span style="font-size:12px;">// Replaced by CF (throws an NSException)+ (id)init { return (id)self;}- (id)init { return _objc_rootInit(self);}</span>
<span style="font-size:12px;"></span><pre>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;}
- iOS NSObject源代码(1)alloc和init
- iOS new和alloc init的区别
- iOS new 和alloc/init 的区别
- ios new和alloc init的区别
- iOS alloc、init和new方法
- [[NSObject alloc] init] 与 [NSObject new] 的区别
- iOS开发之new 和 alloc init的区别
- iOS 中 new 和 alloc init 的区别
- iOS 中 new 和 alloc init 的区别
- iOS中alloc/init和new的区别
- ios-关于new和alloc init的区别
- iOS中alloc与init
- iOS中alloc与init
- iOS new与alloc/init介绍
- iOS new与alloc/init的区别
- ios中alloc init new的区别
- iOS开发中 new与alloc/init的区别 及 [NSArray array] 和 [[NSArray alloc]init] 及 self. 和 _ 的区别
- iOS开发中 new与alloc/init的区别 及 [NSArray array] 和 [[NSArray alloc]init] 及 self. 和 _ 的区别
- GoldenGate ->Kafka 输出CSV主键更新问题
- UE4 4.13 VR FPS 继续优化
- RHCE对你职场的帮助
- CS229-Machine Learning notes Lecture1 机器学习的动机与应用
- css3图片循环旋转
- iOS NSObject源代码(1)alloc和init
- Apache配置中ProxyPassReverse指令的含义
- Deep Learning模型之:CNN卷积神经网络(一)深度解析CNN
- C# 加载C++下DLL 的格式转换
- OpenGL ES Shader 多重纹理
- 基于Canvas的能力图
- 第k短路的求法
- 如何利用github搭建一个个人网站
- 基于深层神经网络的命名实体识别技术