6.4.8 inline函数
函数的引入可以减少程序的代码量,使得函数程序可以在代码间共享。但函数调用需要一些时空开销。在调用函数时,先要中断调用函数,将执行流程转移到被调函数中,待被调函数执行完毕后,返回调用函数。因此,在调用函数前,应保护被调函数现场,记录程序当前位置,以方便从被调函数中返回,恢复现场,并从原来的位置处继续执行。
对于较长的函数,这种开销可以忽略不计,但对于一些很短的、频繁调用的函数体,这种开销就不能忽视。举例来说,代码6.3中的print()函数定义如下所示。
void print(int x) { cout<<x<<endl; }
可能有的读者会问:“定义这么短的函数有意义吗?它有哪些好处呢?”
具体来说,使用函数可以提高程序的可读性,方便阅读和修改。另外,函数程序可方便地用于共享,可以重复使用,但也如前面所述,当这种简短函数被频繁地调用时,调用函数的开销会降低应用程序的性能和执行效率。
inline函数的提出正是为了解决这个问题,提高程序的运行效率。
定义inline函数的方法很简单,只要在普通的函数定义前加修饰符inline即可,如下所示。
inline void print(int x) { cout<<x<<endl; }
在编译时,编译器会将程序中的inline函数都用其函数体来代替,执行的计算完全相同,虽然目标程序的代码量会增加,但节省了非内联函数调用时的栈内存的创建和释放开销,这是一种以空间(文件大小)来换时间(提高运行效率和性能)的方法。
关于inline函数有以下4点注意事项。
(1)在一个文件中定义的inline函数不能在另一个文件中使用。
(2)inline函数应简洁,只用几个语句,如果语句较多,不适合于定义为inline函数。
(3)inline函数体中,不能有循环语句、if语句或switch语句,否则,即使函数定义时使用了inline关键字,编译器也会将其当成普通函数来处理。
(4)inline函数应在调用和声明前进行定义,否则,有的编译器会将其当成普通函数,不能起到预期的效果,无法提高程序的运行效率,而有的编译器可能会报错(如VC6),见代码6.11。
代码6.11 inline函数的引用InlineFunction
<————————————-文件名:example611.cpp——————————————-> 01 #include<iostream> 02 using namespace std; 03 inline void print(int n)//inline函数print()定义 04 { 05 cout<<n<<endl; 06 cout<<"n的地址是:"<<&n<<endl; 07 } 08 int main() 09 { 10 void print(int);//函数声明 11 int m=6; 12 cout<<"m的地址是:"<<&m<<endl; 13 print(m);//函数调用 14 return 0; 15 }
输出结果如下所示。
m的地址是:0013FF7C 6 n的地址是:0013FF2C
【代码解析】在代码第3行,如果inline函数print()定义在main()函数之后,VC6编译器会给出错误信息,提示无法找到print()函数。