iOS-alloc、init与new初探

721 阅读2分钟

iOS中alloc、init与new的作用?

首先我们看一段代码

Person *p1 = [Person alloc];
Person *p2 = [p1 init];
Person *p3 = [p1 init];
NSLog(@"%@ - %p",p1,&p1);
NSLog(@"%@ - %p",p1,&p2);
NSLog(@"%@ - %p",p1,&p3);

打印结果:

<Person: 0x600000408640> - 0x7ffee0dc89b8
<Person: 0x600000408640> - 0x7ffee0dc89b0
<Person: 0x600000408640> - 0x7ffee0dc89a8

得出结论:P1、P2、P3三个不同的指针指向了同一块内存区域:

接下来我们分析一下alloc的流程,如下图:(我们需要下载objc源码配置

从源码流程中我们可以看出,alloc方法主要是做申请开辟内存,并伴随初始化了一个属性isa(8个字节)

size_t instanceSize(size_t extraBytes) {
    size_t size = alignedInstanceSize() + extraBytes;
    // CF requires all objects be at least 16 bytes.
    if (size < 16) size = 16;
    return size;
}

一个类对象最少占16个字节,是为了让编译器容易读取地址(空间换时间),且防止野指针。

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;
}

init方法直接返回的alloc对象self本身,这也是文章开始P1、P2、P3指向同一块内存地址的原因。同时也是为了方便开发人员能够在工厂设计开发的时候去扩展、自由定义。

new函数源码:

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

可以看出,[className new]基本等同于[[className alloc] init] ,区别在于:

1、new出的对象无法调用各种initWith...方法;
2、alloc分配内存的时候使用了zone,这个zone它是给对象分配内存的时候,把关联的对象分配到一个相邻的内存区域内,以便于调用时消耗很少的代价,提升了程序处理速度。