alloc init 和new的区别

710 阅读1分钟

本篇文章采用的源码是objc4-818版本

经常使用的创建对象的两种方式:

UIView *v = [[UIView alloc] init];
UIView *v = [UIView new];

这两个什么区别的呢? 我们在源码中找到文件 (Source/NSObject.mm) 中找到alloc方法和new方法的实现 先看看 new

+ (id)new {
    return [callAlloc(self, false/*checkNil*/) init];
}

new 方法调用了 callAlloc 这个方法, 然后 init

callAlloc 方法的实现 

//init方法 2557
- (id)init {
    return _objc_rootInit(self);
}

再来看看 alloc 和 init

+ (id)alloc {
    return _objc_rootAlloc(self);
}
- (id)init {
    return _objc_rootInit(self);
}

alloc 方法中 使用这个方法初始化, 然后同样调用了 callAlloc 方法就行

// 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*/);
}

通过对比发现 都是调用了 callAlloc 这个函数, 但是的呢? new 的时候传了两个参数 alloc 的时候传了3个参数, 就是这个 bool allocWithZone=false

// 先调用的这个 1921
// Call [cls alloc] or [cls allocWithZone:nil], with appropriate
// shortcutting optimizations.
static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
#if __OBJC2__
    if (slowpath(checkNil && !cls)) return nil;
    if (fastpath(!cls->ISA()->hasCustomAWZ())) {
        return _objc_rootAllocWithZone(cls, nil);
    }
#endif

    // No shortcuts available.
    if (allocWithZone) {
        return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);
    }
    return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
}

就是说 alloc 的时候走的是 allocWithZone:new 的时候走的是 alloc

区别

  1. alloc 在分配内存的时候使用了 allocWithZone, 它是在给对象分配内存的时候把关联的对象分配到一个相邻的区域内, 以便于调用时消耗很少的内存, 提升程序的处理速度
  2. alloc init 的时候可以重新 init 自定义程度高一些, new 的话直接固定死了

End