C++ inline函数
内联函数:inline 函数避免函数调用的开销
将函数指定为 inline 函数,(通常)就是将它在程序中每个调用点上“内联地”展开。假设我们将 shorterString 定义为内联函数,则调用:
// find longer of two strings const string &shorterString(const string &s1, const string &s2) { return s1.size() < s2.size() ? s1 : s2; } cout << shorterString(s1, s2) << endl;
在编译时将展开为:
cout << (s1.size() < s2.size() ? s1 : s2) << endl;
A.inline 说明对于编译器来说只是一个建议,编译器可以选择忽略这个。一般来说,内联机制适用于优化小的、只有几行的而且经常被调用的函数。大多数的编译器都不支持递归函数的内联。一个 1200 行的函数也不太可能在调用点内联展开。
B.内联函数应该在头文件中定义,这一点不同于其他函数。inline 函数的定义对编译器而言必须是可见的,以便编译器能够在调用点内联展开该函数的代码。此时,仅有函数原型是不够的。在头文件中加入或修改 inline 函数时,使用了该头文件的所有源文件都必须重新编译。
C.关键字inline 必须与函数定义体放在一起才能使函数成为内联,仅将inline 放在函数声明前面不起任何作用。但成员函数函数不受此限制.
如下风格的函数Foo 不能成为内联函数:
inline void Foo(int x, int y); // inline 仅与函数声明放在一起 void Foo(int x, int y){}
而如下风格的函数Foo 则成为内联函数:
void Foo(int x, int y); inline void Foo(int x, int y) // inline 与函数定义体放在一起{}
所以说,C++ inline函数是一种“用于实现的关键字”,而不是一种“用于声明的关键字”。一般地,用户可以阅读函数的声明,但是看不到函数的定义。尽管在大多数教科书中内联函数的声明、定义体前面都加了inline 关键字,但我认为inline 不应该出现在函数的声明中。这个细节虽然不会影响函数的功能,但是体现了高质量C++/C 程序设计风格的一个基本原则:声明与定义不可混为一谈,用户没有必要、也不应该知道函数是否需要内联。
D.定义在类声明之中的成员函数将自动地成为内联函数
例如
class A { public:void Foo(int x, int y) { } // 自动地成为内联函数 }
将成员函数的定义体放在类声明之中虽然能带来书写上的方便,但不是一种良好的编程风格,上例应该改成:
// 头文件 class A { public: void Foo(int x, int y); } // 定义文件 inline void A::Foo(int x, int y){}
注意事项
使用内联函数应注意的事项
内联函数具有一般函数的特性,它与一般函数所不同之处只在于函数调用的处理。一般函数进行调用时,要将程序执行权转到被调用函数中,然后再返回到调用它的函数中;而内联函数在调用时,是将调用表达式用内联函数体来替换。在使用内联函数时,应注意如下几点:
1.在内联函数内不允许用循环语句和开关语句。
如果内联函数有这些语句,则编译将该函数视同普通函数那样产生函数调用代码,递归函数(自己调用自己的函数)是不能被用来做内联函数的。内联函数只适合于只有1~5行的小函数。对一个含有许多语句的大函数,函数调用和返回的开销相对来说微不足道,所以也没有必要用内联函数实现。
2.内联函数的定义必须出现在内联函数第一次被调用之前。
3.内联函数的优点
1).和宏类似的高效率
2).内联函数是真正的函数,可以访问对象的私有和保护成员,编译器对它可以进行参数有效性检测等。
4.内联函数在何时使用
1).可以完全取代表达式形式的宏定义
2).在函数内容非常简单又需要大量重复调用的时候