iOS 的尾调用优化原理

Posted 喵喵yy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS 的尾调用优化原理相关的知识,希望对你有一定的参考价值。

背景:

今天聊代码规范的问题的时候说了一下尾调用的问题。

 

一:概念:

什么是尾调用?

尾调用(Tail Call):某个函数的最后一步仅仅只是调用了一个函数(可以是自身,可以是另一个函数)。

注意 “仅仅” 两个字。

 

例子:

// 尾调用:
- (NSInteger)funcA:(NSInteger)num {

    /*  Some codes... */

    if (num == 0) {
        return [self funcA:num];// 尾调用->自身
    }    

    if (num > 0) {
        return [self funcB:num];// 尾调用->函数funcB
    }    

    return [self funcC:num];// 尾调用->函数funcC
}

 

// 不是尾调用1:
- (NSInteger)funcA:(NSInteger)num {

    NSInteger num = [self funcB:(num)];

    return num;// 不是尾调用->最后一步是返回一个值,而不是调用一个函数
}

 

// 不是尾调用2:
- (NSInteger)funcA:(NSInteger)num {

    return [self funcB:(num)] + 1;// 不是尾调用->原因:最后一步不仅调用了函数还有 +1 操作
}

 

二:优化点(尾调用优化在Release模式下才会有,Debug模式下没有。)

 

 

 

例子:一直开辟新的栈空间(最后会栈溢出,最终导致崩溃。空间复杂度O(n),时间复杂度O(n)。)

 

例子:尾调用的优化可以重复利用栈空间(重用栈帧,不申请栈空间。
空间复杂度O(1),时间复杂度O(n)。)

 

 

 

 

 

三、总结

总结:
1. 尾调用:某个函数的最后一步仅仅调用了一个函数(可以是自身,可以是另一个函数)。
2. OC的尾调用优化的本质是:栈帧的复用
3. 尾调用优化实现原理:当函数A的最后一步仅仅是调用另一个函数B时(或者调用自身函数A),这时,因为函数A的位置信息和内部变量已经不会再用到了,直接把函数A的栈帧交给函数B使用。


四:附加思考:

 

 

 

 

 

 

 

 

思考:尾调用尾部加0可以达到尾调用优化,加.0就不能达到,是为什么呢?

 

 

 

 

 

 

注:

参考:https://www.jianshu.com/p/9e3cd9b1095a

 

以上是关于iOS 的尾调用优化原理的主要内容,如果未能解决你的问题,请参考以下文章

一个很Cool的Idear->Python的尾递归优化

Swift 编程中的尾递归和蹦床译

cordova与ios native code交互的原理

Oz 中的尾递归优化

尾调用优化

如何优化C ++代码的以下片段 - 卷中的零交叉