对递归函数的一点小理解

对于递归函数,大家都很熟悉了,对于解析一些复杂数据结构方面,能够使代码非常简洁,明了。

从我的理解来说,递归函数一般效率比较低,而且自身特点导致的限制也不少:

1. 效率低

一个非常简单的例子数数吧,从1数到1M。
对于循环实现的:
  

递归实现:

对于循环实现,函数相当于:

对于递归实现,相当于:

  对于第一种实现,不需要函数调用,只需要重复1M-1次跳转,即Loop
  对于递归实现,需要1M-1次函数调用
 
让我们来看看跳转指令和函数调用指令的区别:
对于跳转指令,相当于将目标指令地址附给eip寄存器,该条指令结束后计算机会从eip指向的指令地址开始执行。
即:
   jmp xxxx       ;此指令的工作是仅仅是修改 eip的值为xxxx对应的地址, 当该指令结束后系统会从eip指向处开始执行

对于函数调用指令call,则作了更多隐藏工作:
   call xxxx      ;因为call指令是需要返回的,所以需要保存返回后的地址,该地址为执行call指令时的eip值+5(call指令的长度为5,32位系统)
                  ;然后将这个值保存到堆栈上,之后才能将xxxx对应的值装载到eip寄存器之中,开始实际跳转动作
                  ;自过程结束后,再将保存在堆栈上的值重新附给eip,这样程序才能从call xxxx的下一条指令开始执行。
所以call xxxx 基本相当于
   push eip+5
   mov eip, xxxx
   jmp eip
  
ret 相当于:
   pop eip ;即将前面的eip+5重新附给eip
   jmp eip

从这里基本可以看出:递归函数实际上多做了(1M-1)次多余的工作,而且这只是最简单的寒暑,如果自过程中还有很多临时变量,则整个过程中
维护堆栈平衡的开销也将非常可观。


2. 局限性
不知道这个算不算,因为世纪中还没真正遇到过这个问题导致的运行错误。
对于一个最简单的递归函数:
 

 这个函数执行的结果是导致运行栈耗尽,最终程序崩溃,当然最终原因是它缺少适当的递归出口。
 
 不过对于一种极端情况:
 
   
这个函数每次都会在栈上申请 10000 或20000个BYTE, 取决于字符集属性,由于运行栈大小是预先定义好的(2M左右吧),所以该函数也不可避免的导致上面的问题。


综上,对于对效率要求很高的代码应尽量避免使用递归;
      在使用递归时,如果递归深度不能预期, 避免在堆栈上申请只有函数返回才能释放的大块空间,而应该将其放在heap上。

 

以上为个人理解,估计肯定有先人总结过了,但绝非抄袭,同时欢迎拍砖。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值