C++中的内联函数

先看一段代码:

int min(int x , int y)

{

       return ( x < y << x : y ) ;

}

很简单的一个功能,直接用条件操作符 x < y << x : y 就能实现,为什么还要用函数来实现呢?这是因为这段代码与直接用条件操作符 x < y << x : y 相比有诸多好处:

1、  使代码简单易懂。阅读这段代码并解释其含义,以及理解这段代码在做什么,比读一个条件操作符的实例要简单的多,尤其是遇到复杂表达式的时候。

2、  使代码易于维护。当你要改变条件操作符的时候,只需改动该函数一处即可,无论这个函数在整个程序里有多少次被调用。如果不使用函数调用而直接用条件操作符,当该操作符在一个应用中有上百上千甚至更多的时候,可想而知这个工作将是何等的乏味和容易出错。

3、  语义统一,每个测试都保证有相同的实现。

4、  如果其他应用需要,函数可以直接重用,而不必再重写代码。

虽然有如此多的好处,但是调用函数有一个严重的缺点:效率降低。

函数是一种更高级的抽象。它的引入使得编程者只关心函数的功能和使用方法,而不必关心函数功能具体是如何实现的;函数的引入可以减少程序的目标代码,实现程序代码和数据的共享。但是,函数调用同时带来了降低效率的问题,因为调用函数实际上是将程序执行顺序转移到函数所存放在内存中的某个地址,将函数的程序内容执行完后,再返回到转去执行该函数前的地方。这种转移操作要求在转去前要保护现场并记忆执行的地址,转回后先要恢复现场,并按原来保存的地址继续执行。因此,函数调用要有一定的时间和空间方面的开销,于是将影响其效率。特别是对于一些函数体代码不是很大,但又频繁地被调用的函数来讲,解决其效率问题更为重要。

C++为之提供的解决方案就是引入内联函数。

在程序编译时,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体来进行替换。显然,这种做法不会产生转去转回的问题,但是由于在编译时将函数体中的代码被替代到程序中,因此会增加程序的目标代码量,进而增加空间开销,而在时间代价上不象函数调用时那么大,可见它是以目标代码的增加为代价来换取时间的节省的。

定义内联函数的方法很简单,只要在函数定义的前面加上关键字 inline 即可,也就是显式声明内联。内联函数的定义方法与一般函数一样。不一样的是,在程序中调用内联函数时,该函数将在编译时被替代,而不是像一般函数那样在运行时被调用。

内联函数具有一般函数的特性,它与一般函数所不同之处在于函数调用的处理。一般函数进行调用时,要将程序执行权转到被调用函数中,然后再返回到调用它的函数中;而内联函数在调用时,是将调用表达式用内联函数体来替换。

在使用内联函数时,应注意如下几点:

1、  在内联函数内不允许用循环语句和开关语句。

2、  内联函数的定义必须出现在内联函数第一次被调用之前。

3、  内联函数对于编译器来说是一种请求,而不是强制性的命令。程序员可以把函数定义为内联函数,一般情况下,是不会产生任何函数调用的。但是如果编译器认为该函数不适合内联(比如:函数体较大,内联将会产生比调用更大的开销;函数体内有复杂操作,如循环、递归调用等等),将会按一般函数处理之。

4、  在类说明内部定义的函数默认是内联函数,即隐式声明。

这句话将会引起某一些人的误解——既然在类说明内部定义的函数默认是内联函数,那么虚函数也能成为内联函数。

但是事实上,虚函数和内联函数根本就是两码事。

a、  内联函数没有函数地址,它在编译期间静态的展开在目标代码中的调用点。

b、  虚函数是一个函数指针,它指向该函数的内存地址,只有到了运行时刻,系统才会根据被调用对象的实际基类或派生类的类型来动态的选择一个匹配的虚拟函数实例。因此虚函数不能被静态处理。

正如上面第3点注意事项所说,你可以向编译器请求将虚函数声明为inline ,但是到底内联不内联,编译器说了算,基于上面的原因,它可以忽略你的请求,不听你的。

 

秦铭  

2006-12-5 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值