OC底层原理--创建对象(alloc&init&new)都干了啥

2020-09-07  本文已影响0人  laona

alloc源码分析

本次探索主要基于objc4-781源码 进行分析

首先,通过断点调试源码的方式绘制自定义对象执行alloc操作的整体流程如下图所示:

alloc流程图.png

接下来,我们看下每一步具体做了什么

其中的__builtin_expect指令是由gcc引入的,
1、目的:编译器可以对代码进行优化,以减少指令跳转带来的性能下降。即性能优化
2、作用:允许程序员将最有可能执行的分支告诉编译器。
3、指令的写法为:__builtin_expect(EXP, N)。表示 EXP==N 的概率很大。
4、fastpath 定义中 __builtin_expect((x),1) 表示 x 的值为真的可能性更大;即执行 if 里面语句的机会更大
5、slowpath 定义中的 __builtin_expect((x),0) 表示 x 的值为假的可能性更大。即执行 else 里面语句的机会更大

至此,alloc的整个流程我们已经基本了解了,接下来我们看下 init 做了哪些操作

init 源码分析

依然是通过断点跳转至源码具体实现,我们发现 init 的操作异常简单,具体如下:

// Replaced by CF (throws an NSException)
+ (id)init {
    return (id)self;
}

- (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都是直接返回了对象本身,那么苹果这么做用意何在呢?

这里的init主要作用是提供一个构造方法的入口 ,是通过工厂设计(工厂方法模式),这里能使用id强转的原因,主要还是因为 内存字节对齐后,可以使用类型强转为你所需的类型

至此,对于 init 的原理我们也有了了解,那么最后让我们来看一下new具体做了哪些操作

new 源码分析

依然是通过断点跳转至源码具体实现,我们发现 new 的操作异常简单,具体如下:

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

过源码可以得知,new 函数中直接调用了 callAlloc 函数(即 alloc 中分析的函数),且调用了 init 函数,所以可以得出 new 其实就等价于 [alloc init] 的结论

但是一般开发中并不建议使用 new ,主要是因为有时会重写 init 方法做一些自定义的操作,而用 new 初始化时调用的是 NSObjectinit 方法.这种时候就可能会出现无法走到自定义 init 的部分

总结

通过源码调试的方式我们已经了解了对象创建过程中 alloc init new 分别做了哪些东西.了解了这些原理之后可以帮助我们后续更好的理解对象.最后稍微总结下关键点:

上一篇下一篇

猜你喜欢

热点阅读