一、简述
inline关键字放在函数返回类型前,函数实现处必须写inline关键字。关键字inline在函数声明部分可以加也可以不加,建议不加,因为用户不需要知道一个函数是否是内联函数。假如在声明处加了inline,但是在实现处没有加inline,那么此函数被当做普通函数处理。
与普通成员函数不同的是,inline成员函数的实现在头文件中,因为内联函数必须在调用该函数的每个文本文件中定义。可以使用如下书写形式:
//Student.h
class Student
{
public:int min_fun(int a,int b );
}
inline int Student::min_fun(int a,int b )
{
return a < b ? a : b;
}
假如,内联函数的实现写在了源文件中并且在这个源文件以外的文本文件中调用了此内联函数,那么编译可以通过,但是链接器会报“无法解析的外部符号”的错误。
在声明时就实现的函数自动成为内联函数。一个好的编译器能自动决定函数是否应该被当做内联函数使用,不管是否添加inline关键字。
二、内联函数提高程序效率
普通函数的调用要经过“保存现场、转到被调函数执行、执行完毕返回调用处、恢复现场”这一过程,产生时空开销。内联函数是通过代码膨胀来执行的,在内联函数调用处复制函数代码,这样省去了普通函数调用的时空开销,提高了程序执行效率,但是由于代码复制增加了内存开销,所以内联函数应当是小函数、执行耗时短的函数。这也就说明了为什么不能把所有的函数都作为内联函数。
三、不要过度使用内联函数,尤其是大函数,并且内联函数中不要含有循环、判断、选择。
四、注意: 内联函数和宏定义虽然都是代码替换,但是完全不一样,不要把二者混淆; 内联成员函数可以访问成员变量(public private protected),除了比普通成员函数执行快之外,不要刻意区分内联成员函数和普通成员函数。
五、内联函数的链接性是内部的,这意味着函数定义必须在使用函数的文件中。如果将内联函数的定义放在实现文件中,但必须删掉关键字inline,这样函数的链接性将是外部的。
总结:关键字inline必须与函数定义体放在一起才能使函数成为内联,仅将inline放在函数声明前面不起任何作用。所以说,inline是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。
六、慎用内联
内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。以下情况不宜使用内联:
(1)如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。
(2)如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。
类的构造函数和析构函数容易让人误解成使用内联更有效。要当心构造函数和析构函数可能会隐藏一些行为,如“偷偷地”执行了基类或成员对象的构造函数和析构函数。所以不要随便地将构造函数和析构函数的定义体放在类声明中。
一个好的编译器将会根据函数的定义体,自动地取消不值得的内联(这进一步说明了 inline不应该出现在函数的声明中)。
转载自内联函数