30 透彻了解inlining的里里外外

一、了解inline

优点:

  • 可以免除函数调用成本
  • 编译器有能力对inline函数执行语境相关最优化,编译器最优化机制的设计目的是通常是为了优化“不含函数调用”的代码
  • 可能导致较小的目标代码和较高的指令告诉缓存装置击中率

缺点:

  • 对inline函数的每一个调用都以函数本体替换,会增加目标代码的大小
  • 过多的inline会造成程序体积太大、代码膨胀亦会导致额外的换页行为降低高速缓存装置的击中率
  • inline只是对编译器的一个申请,不是强制命令

二、inline声明方式

  • 隐喻方式: 将函数定义于class定义式内
  • 显示方式: 使用inline关键字
    被定义于clas内的friend函数也是被隐喻声明为inline的

三、inline的时机

大多数建置环境在编译过程中进行inlining,某些建置环境可以在链接期完成inlining,少量建置环境(如基于.NET CLI Common Language Infrastructure;公共语言基础设施)的托管环境可以在运行期完成inlining。
为了将一个“函数调用”替换为“被调用函数的本体”,编译器必须知道那个函数长什么样子。

function templates

  • Templates通常也被置于头文件内,因为他一旦被使用,编译器为了将它具现化,需要知道他长什么样子。(某些建置环境可以在链接期才执行template具现化,但是在编译期完成具现化的比较常见。)
  • Template为什么要放在头文件内?
    编译期将各个编译单元(源文件)编译生成目标文件,链接期将目标文件链接生成可执行文件。因此在编译期间具现化则需要将function template的定义置于头文件内,因为此时各个编译单元相互独立,template定义在源文件内,编译器无法吵到,定义在头文件内,不同的编译单元可将头文件包含在本单元内,编译器可以找到模板的定义
  • Template的具现化于inlining无关。若要template具现出来的函数都应该inlined,将此template声明为inline。

四、哪些情况不能inlined

  • 大部分编译器会拒绝太过复杂(例如带有循环或递归)的函数inlining
  • 对所有的virtual函数的调用(除非式最平淡无奇的)也都会使inlining落空,virtual意味着“等待,直到运行期才能确定调用哪个函数”,而inline意味着“执行前,先将调用动作替换为被调用的函数的本体”。在编译期间,编译期无法确定virtual函数的函数本体,所以无法inlined。
  • 编译期通常不对“通过函数指针而进行的inline函数调用”实施inlining。这意味着对inling函数的调用有可能不被inlined,取决于该调用方式。如,对inline函数取地址,编译器会生成一个outlined的函数本体,通过该地址调用inline函数,则不会实施inlining。
  • 有时候编译器会生成构造函数和析构函数的副本,如此一来他们就可以获得指针指向那些函数,在array内部元素的构造和析构过程中使用。
  • -构造函数和析构函数往往是inlining的糟糕候选人。在继承体系中,即使是空的构造函数被inlined,编译器也可能生成一系列代码,因为基类构造也可能inlined,基类成员变量中的构造函数也可能被inlined,如此一来,构造函数inlined的代码会很复杂,析构函数同样如此。

五、inline的成本

  • 程序接口库中包含inline函数,一旦inline函数改变则客户需要重新编译代码
  • 大部分调试器对inline函数都束手无策。因为inline函数会被替换到调用处,而在定义处的inline函数没有被调用,不能加断点。许多建置环境仅仅只能在调试版程序中禁用发生inlining。

六、如何使用inline

  • 一开始先不要将任何函数声明为inline,或至少将inlining施行范围局限在那些“一定成为inline”或“十分平淡无奇”的函数身上。
  • 慎重使用inline是对日后使用调试器带来帮助
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值