likes
comments
collection
share

alloc init 与 new 的区别

作者站长头像
站长
· 阅读数 49

代码

先来看一段打印

Person *p1 = [Person alloc];
Person *p2 = [p1 init];
Person *p3 = [p1 init];

NSLog(@"%@ - %p - %p", p1, p1, &p1); 
NSLog(@"%@ - %p - %p", p2, p2, &p2); 
NSLog(@"%@ - %p - %p", p3, p3, &p3); 
//打印结果
//<Person: 0x6000022f4160> - 0x6000022f4160 - 0x7ffee7a11078
//<Person: 0x6000022f4160> - 0x6000022f4160 - 0x7ffee7a11070
//<Person: 0x6000022f4160> - 0x6000022f4160 - 0x7ffee7a11068

%p -- p1是打印对象的地址

%p -- &p1是打印p1在地址空间的地址

alloc init 与 new 的区别 三个指针变量指向同一块内存空间,p1 p2 p3是放在栈空间,所以每一个指针变量地址是不同的; 因为是在栈空间分配的,所以栈空间从高到低;又因为64位设备,指针大小8字节,所以从0x7ffee7a11078依次减去0x8。

实际上,init 什么也不做,只是给开发者使用工厂模式提供了一个接口,alloc是分配内存空间,new等于先调用alloc 再init.

源码

源码验证了这一点

new 源码
+ (id)new
{
    id newObject = (*_alloc)((Class)self, 0);
    Class metaClass = self->isa;
    if (class_getVersion(metaClass) > 1)
        return [newObject init];
    else
        return newObject; 
}

alloc/init源码:
+ (id)alloc
{
    return (*_zoneAlloc)((Class)self, 0, malloc_default_zone());
}
 
- (id)init
{
    return self;
}

alloc流程

alloc主要负责开辟内存,它的核心流程如下:

  1. 先计算出需要的内存空间大小 size = cls->instanceSize(extraBytes);
  2. 申请内存 向系统申请开辟内存,返回地址指针 obj = (id)calloc(1, size);
  3. isa绑定 关联到相应的类 obj->initInstanceIsa(cls, hasCxxDtor);

alloc init 与 new 的区别

结论

如果不重写init方法,使用new会走父类的init方法;如果我们自定义类里重写了init方法,使用new会走到重写的这个方法,但是如果我们自定义的initWithXXX方法,new 就会调用super init方法,走父类的init方法,走不到自定义的initWithXXX方法.

最后附上 苹果官方源码官方文档

转载自:https://juejin.cn/post/6980915451136049182
评论
请登录