9.2 内联函数
在解决C++中宏访问private类成员的问题过程中,所有和预处理器宏有关的问题也随之排除了。这是通过使宏被编译器控制来实现的。在C++中,宏的概念是作为内联函数(inline function)来实现的,而内联函数无论从那一方面上说都是真正的函数。内联函数能够像普通函数一样具有我们所有期望的任何行为。惟一不同之处是内联函数在适当的地方像宏一样展开,所以不需要函数调用的开销。因此,应该(几乎)永远不使用宏,只使用内联函数。
任何在类中定义的函数自动地成为内联函数,但也可以在非类的函数前面加上inline关键字使之成为内联函数。但为了使之有效,必须使函数体和声明结合在一起,否则,编译器将它作为普通函数对待。因此
没有任何效果,仅仅只是声明函数(这不一定能够在稍后某个时候得到一个内联定义)。成功的方法如下:
注意,编译器将检查函数参数列表使用是否正确,并返回值(进行必要的转换)。这些事情是预处理器无法完成的。假如对于上面的内联函数写成一个预处理器宏的话,将得到不想要的副作用。
一般应该把内联定义放在头文件里。当编译器看到这个定义时,它把函数类型(函数名+返回值)和函数体放到符号表里。当使用函数时,编译器检查以确保调用是正确的且返回值被正确使用,然后将函数调用替换为函数体,因而消除了开销。内联代码的确占用空间,但假如函数较小,这实际上比为了一个普通函数调用而产生的代码(参数压栈和执行CALL)占用的空间还少。
在头文件中,内联函数处于一种特殊状态,因为在头文件中声明该函数,所以必须包含头文件和该函数的定义,这些定义在每个用到该函数的文件中,但是不会出现产生多个定义错误的情况(不过,在任何使用内联函数地方该内联函数的定义都必须是相同的)。
9.2.1 类内部的内联函数
为了定义内联函数,通常必须在函数定义前面放一个inline关键字。但这在类内部定义内联函数时并不是必须的。任何在类内部定义的函数自动地成为内联函数。如下例:
两个构造函数和print()函数都默认为内联函数。注意在main()函数中使用内联函数是自然而然的事。一个函数的逻辑行为必须相同(要不然会出现编译错误),不管它是否是内联函数,我们就会看到,惟一不同之处在于它们的效率不一样。
当然,因为类内部的内联函数节省了在外部定义成员函数的额外步骤,所以我们一定想在类声明内每一处都使用内联函数。但应记住,使用内联函数的目的是减少函数调用的开销。但是,假如函数较大,由于需要在调用函数的每一处重复复制代码,这样将使代码膨胀,在速度方面获得的好处就会减少(惟一可靠的办法就是在程序上试验,看看使用内联函数的效果如何)。