浅谈尾递归的优化方式
.cont(this.n * r); } } public static int FactorialLoopOptimized3(int n, Func<int, int> continuation) { while (true) { if (n == 0) break; continuation = new Continuation(continuation, n).Invoke; n--; } return continuation(1); } 其实这才是FactorialContinuation的“直译”,也是编译器能够进行优化。不过朋友们应该也能够看 出,这只是一个Continuation对象套着另一个Continuation对象。如果形成了数万个Continuation对象的 嵌套,在最终调用最外层的Continuation时,每个内部的Continuation也会在调用时往同一个堆栈中不断 累加,最终还是会造成堆栈溢出。因此,如果使用了Continuation,还是无法简单把递归优化成循环来避 免堆栈溢出的。编译器还必须进行其他方面的优化。 方法尾调用的优化 上一篇文章曾经谈到:“与普通递归相比,由于尾递归的调用处于方法的最后,因此方法之前所积累 下的各种状态对于递归调用结果已经没有任何意义,因此完全可以把本次方法中留在堆栈中的数据完全清 除,把空间让给最后的递归调用。这样的优化便使得递归不会在调用堆栈上产生堆积,意味着即时是“无 限”递归也不会让堆栈溢出”。这其实才是尾递归的“正统”优化方式,那么我们先暂时忘记之前的“循 环优化”,从最简单的示例中查看这样的优化是如何进行的。还是最简单的“尾递归”阶乘:
它的IL代码是:
在这个问题上,我们还需要观察它的汇编代码(为了不干扰文章内容,老赵会把获取汇编代码的做法 单独写一篇文章,稍后发布),如下:
|
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |