当前位置: 首页 > wzjs >正文

无锡网站策划公司企业管理咨询机构

无锡网站策划公司,企业管理咨询机构,天津seo优化,自然资源部网站绿色矿山建设C尾调用优化 什么是尾调用?描述无返回值函数最后调用函数也可能做尾调用优化 例子关键特征(写法) 尾调用和尾递归的区别?为什么尾调用优化可以提高效率?通常的递归调用:尾调用优化:为什么栈帧复…

C++尾调用优化

  • 什么是尾调用?
    • 描述
      • 无返回值函数最后调用函数也可能做尾调用优化
    • 例子
    • 关键特征(写法)
  • 尾调用和尾递归的区别?
  • 为什么尾调用优化可以提高效率?
    • 通常的递归调用:
    • 尾调用优化:
    • 为什么栈帧复用就可以提高效率
      • 函数调用和尾调用优化避免的开销
        • 栈空间分配
        • 栈帧入栈
        • 内存访问与缓存
  • 如何判断编译器是否做了尾调用优化?
    • 代码示例

尾调用优化(Tail Call Optimization, 简称 TCO)是现代编译器中一项重要的优化技术,它能在某些条件下避免函数调用时的栈增长,从而减少运行时内存开销,提高程序性能。

本文回答了以下几个问题:

  1. 什么是尾调用?
  2. 尾调用和尾递归的区别?
  3. 为什么尾调用优化可以提高效率?
  4. 如何判断编译器是否做了尾调用优化?

【一句话】
函数调用有栈增长的开销,尾调用优化省去了函数调用入栈的开销。

什么是尾调用?

描述

尾调用是指:一个函数在“最后一步”调用另一个函数,并将其返回值直接返回。

【补充】

无返回值函数最后调用函数也可能做尾调用优化

如果函数A是无返回值,只要函数A在最后调用函数B,最后指的是调用函数B后没有其他操作,那编译器也是有可能会做尾调用优化的
因为尾调用的关键在于函数A调用函数B后,还需不需要用到函数A中的信息,如果不需要再用了,那么也就没有了将函数A相关信息入栈的必要,也就能直接复用当前的栈帧了。

例子

int foo(int x) {return bar(x);  // ← 这是一个尾调用
}
void foo_(int x) {bar(x);  // ← 这也是一个尾调用
}

关键特征(写法)

调用另一个函数之后,不再进行其他操作,直接返回。

尾调用和尾递归的区别?

尾递归就是尾调用中最后一个函数是调用自己,形成递归。
尾递归优化,编译器实际上可能把递归函数转换为循环实现。

// 原始尾递归
int sum(int n, int acc = 0) {if (n == 0) return acc;return sum(n - 1, acc + n); // 尾递归调用
}// 优化后(编译器可能转为循环)
int sum(int n, int acc = 0) {while (n > 0) {acc += n;n--;}return acc;
}

为什么尾调用优化可以提高效率?

通常的递归调用:

每调用一次函数,就在栈上分配一个新栈帧来保存局部变量和返回地址。

尾调用优化:

编译器可以直接复用当前栈帧来执行下一个函数调用,避免了栈帧的增长。

为什么栈帧复用就可以提高效率

首先我们需要明白函数调用时发生了什么,知道了栈帧生成的开销,才能知道为什么栈帧复用可以提高效率。

函数调用和尾调用优化避免的开销

栈空间分配

每次函数调用,系统都会为该调用分配一个新的栈帧(stack frame),用来保存局部变量、返回地址、参数、寄存器状态等信息。函数返回时,这个栈帧会被销毁。

【尾调用优化】
译器做了尾调用优化,就可以复用当前函数的栈帧,直接跳转到被调用函数,而不再分配新的栈帧。这样就避免了频繁分配和释放栈帧的开销。

栈帧入栈

栈空间分配后,需要把栈帧压入栈中,而在递归调用时,很容易出现深度过大导致的栈溢出。

【尾调用优化】
尾调用优化通过复用栈帧,使得递归调用不再增加栈深度,相当于变成了循环,极大降低了栈空间需求。

内存访问与缓存

栈帧的分配和释放涉及内存操作,虽然CPU有多级缓存,但频繁的内存访问仍然影响性能。

【尾调用优化】
栈帧频繁分配释放会带来内存操作,增加缓存失效风险,复用栈帧则降低了内存访问压力,有助于提升CPU缓存命中率,进一步提升性能。

如何判断编译器是否做了尾调用优化?

我们可以通过查看生成的汇编代码来判断是否进行了优化。

生成汇编的方法可以看看我的这篇博客C++中switch-case的性能优化策略详解

代码示例

int bar(int x) {return x * 2156 + 15484;
}int foo(int x) {x++;return bar(x * 5); 
}

x86-64 gcc 编译,不开启优化

"_Z3bari":push    rbpmov     rbp, rspmov     DWORD PTR [rbp-4], edimov     eax, DWORD PTR [rbp-4]imul    eax, eax, 2156add     eax, 15484pop     rbpret
"_Z3fooi":push    rbpmov     rbp, rspsub     rsp, 8mov     DWORD PTR [rbp-4], ediadd     DWORD PTR [rbp-4], 1mov     edx, DWORD PTR [rbp-4]mov     eax, edxsal     eax, 2add     eax, edxmov     edi, eaxcall    "_Z3bari"  ; 注意在没有开启优化的情况下,是直接通过call指令调用函数,而这就会涉及到上一节讲的函数调用的开销。leaveret

开启-O2优化后

【注意】
这里有一点要提及,编译器有可能会做内联优化,这是另一种优化手段,但是本文想讨论的是尾调用优化,在函数体过于简单的情况下(例如本文提供的案例),编译器更倾向于使用内联优化,因此为了避免内联优化,我们必须对函数做一点修改,变成以下的样式,来明确规定不允许内联。

// 增加__attribute__((noinline)) 明确告知编译器不用内联【注意,这个标记是GCC和Clang支持的,MSVC或者其他编译器可能有不一样的标记】
__attribute__((noinline)) int bar(int x) {return x * 2156 + 15484;
}int foo(int x) {x++;return bar(x * 5);  // 这是一个“尾调用”!
}
"_Z3bari":imul    eax, edi, 2156add     eax, 15484ret
"_Z3fooi":lea     edi, [rdi+5+rdi*4]jmp     "_Z3bari" ; 直接跳转而非 call ⇒ 没有新栈帧产生

使用了jmp而不是call,说明这里栈帧复用,TCO 生效。


文章转载自:

http://2JcykltF.rqqLp.cn
http://SQSTiAcE.rqqLp.cn
http://jz9SZmx9.rqqLp.cn
http://VU0xWNb1.rqqLp.cn
http://R65vd2Mq.rqqLp.cn
http://UmPSBp5W.rqqLp.cn
http://mFOsxYjd.rqqLp.cn
http://7fuT2K8m.rqqLp.cn
http://QG1zrrd6.rqqLp.cn
http://K2EU7tKb.rqqLp.cn
http://Ujw6GICQ.rqqLp.cn
http://P8MYGfxg.rqqLp.cn
http://iNguGWSC.rqqLp.cn
http://Ui9CAz0y.rqqLp.cn
http://4ahxlhC3.rqqLp.cn
http://8uvcP1zt.rqqLp.cn
http://igOCfnWw.rqqLp.cn
http://NGspLxhC.rqqLp.cn
http://hotpa9XU.rqqLp.cn
http://F0lP27rv.rqqLp.cn
http://iSTmy6qN.rqqLp.cn
http://UlyslRMk.rqqLp.cn
http://vnkMo0AI.rqqLp.cn
http://oyXlndrR.rqqLp.cn
http://QWbMyU8e.rqqLp.cn
http://CGjuRfRR.rqqLp.cn
http://saNSDswT.rqqLp.cn
http://yNyI15wu.rqqLp.cn
http://xzeVfmYT.rqqLp.cn
http://yuH8Uu0x.rqqLp.cn
http://www.dtcms.com/wzjs/733611.html

相关文章:

  • 网站建设与管理维护书籍网站快照历史
  • 建设邯郸网站百度收录要多久
  • 企业网站模板下载哪家好怎么用vps做网站
  • 大良网站建设基本流程高端网络培训课程
  • 深圳做企业网站的公司甘肃城乡建设厅网站首页
  • 中山模板建站代理网站空间到期怎么续费
  • 阿里云个人网站制作随便来一个公司邮箱
  • 网站建设wuliankj北京展示型网站
  • seo主管的seo优化方案seo公司培训课程
  • 站长统计app进入网址新版品牌创意型网站建设
  • 个人网站需要哪些内容wordpress客户使用的后端
  • mip网站建设做牙的网站叫什么
  • 工装网站建设方案用户体验不好的网站
  • 网站网页区别是什么机械加工分类
  • 企业网站要怎么建设久久信息网
  • 应用公园app平台官网长春网站建设SEO优化营销
  • 做免费网站怎么做企业建立网站需要什么条件
  • app免费制作网站软件公司做网站推广科目
  • 宁夏建设厅官方网站杭州网站制作模板
  • 网站服务器建设的三种方法移动网络
  • 湛江网站建设方案策划如何在网上推广自己
  • 织梦网站字体创业做什么好
  • 模板网站可以自己买空间吗吗口碑营销方案
  • 广西平台网站建设报价每天干每天做网站
  • 高端品牌网站建设注意事项进行网站开发前 需要干什么
  • 深圳做微信网站公司哪家好南宁网站建设哪家公
  • 中国建设工程造价信息网站视频网站超链接怎么做
  • 浙江做网站公司电子商务有限公司是干什么的
  • 男人女人晚上做那事网站建设网站教程视频
  • 公司建设网站的意义百度智能云官网