OC 的 alloc init new 总结

540 阅读2分钟

alloc init new 总结

本文记录的并不完整, 只是一些关键点, 自己做为笔记复习用的. 不喜勿喷....

我做为一个 iOSer, 经常会创建一个类, 然后实例化对象, 因为我们着重总结 alloc 和 init 两个方法, 所以就只展示核心代码, 如下:

Person *p = [[Person alloc] init];

那么 alloc 和 init 两个方法到底做了什么呢 ? 下面将详细说明, 因为探索过程比较繁, 所以就不写了, 直接上结果, 都是干货.

alloc

通过查看 objc 源码发现, alloc 方法主要做了三件事情.

  1. 计算申请内存空间大小.
  2. 开辟内存空间.
  3. 把类的信息关联到 isa 上.

1. 计算申请内存空间大小

计算需要开辟的内存空间大小, 调用的是:

size_t size;
size = cls->instanceSize(extraBytes);

根据实际大小, 按照 16 字节 对齐原则给出需要申请开辟的内存空间的大小.

特别说明: 开辟内存最小是 16 字节, 即OC对象最小是 16 字节.

2. 开辟内存空间

开辟内存空间调用的是:

id obj;
obj = (id)calloc(1, size);

根据 size 去申请完内存空间, 将内存空间的首地址返回给 obj; 实际在开辟内存空间的时候还有一次计算, 也是按照16 字节对齐原则去分配的内存空间.

3. 把类的信息关联到 isa 成员上

初始化 isa 调用的是:

obj->initInstanceIsa(cls, hasCxxDtor);

isa 是一个union isa_t 类型的联合体, 定义在 isa.h 中, 是 NSObject 对象的和一个成员变量. 包含了类的各种信息. 被声明在 struct objc_object 这个结构体中.

struct objc_object {
private:
    isa_t isa;
public:
   // 方法....
}

init

通过查看 objc 源码发现, init 方法什么事情都没做, 而是直接 return (id)self;. 没什么复杂的. 那么问题来了, 苹果为什么还要这样写呢 ?

init 只是一个构造方法, 为我们自定义类的时候重写提供便利. 自定义类往往会有自己的构造方法, 即重写 init, 如 - (instancetype)initWithName: (NSString *)name;

new

通过查看源码, new 调用的是 [callAlloc(self, false) init], 相当于调用了 alloc init 两个方法, 区别就在于, new 不会调用自定义的构造方法, 所以日常开发中不建义使用 new.