alloc init 与 new 的区别
代码
先来看一段打印
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在地址空间的地址
三个指针变量指向同一块内存空间,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主要负责开辟内存,它的核心流程如下:
- 先计算出需要的内存空间大小
size = cls->instanceSize(extraBytes);
- 申请内存 向系统申请开辟内存,返回地址指针
obj = (id)calloc(1, size);
- isa绑定 关联到相应的类
obj->initInstanceIsa(cls, hasCxxDtor);
结论
如果不重写init方法,使用new会走父类的init方法;如果我们自定义类里重写了init方法,使用new会走到重写的这个方法,但是如果我们自定义的initWithXXX方法,new 就会调用super init方法,走父类的init方法,走不到自定义的initWithXXX方法.
转载自:https://juejin.cn/post/6980915451136049182