C++ 内联函数
内联函数的目的在于提高效率。C++在编译时会将每个内联函数的调用点用函数体展开,如下:
inline int max(int a, int b) { return a > b ? a : b; } 则调用: cout<<max(a, b)<<endl; 在编译时展开为: cout<<(a > b ? a : b)<<endl;
从而避免了调用函数的额外开销。
关键字
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 与函数定义体放在一起 { ... }
- 类的成员函数如果是定义在类的内部,则默认是内联函数,如果是定义在类的外部则默认不是内联函数,除非在这个外部定义的函数前用关键字
inline
修饰 如果内联函数定义在源文件中,那么就只有该源文件可以调用到内联函数,这是和普通函数不同的地方。所以如果要在多个源文件中调用同一个的内联函数,则要求这些源文件里都存在该内联函数的定义而且完全相同才行。正因为如此,内联函数的声明和定义一般都放在头文件中,利用编译器导入和源文件中,从而保证各源文件的内联函数定义一样。
我们来看一个例子:A.h : class A { public: A(int a, int b) : a(a),b(b){} int max(); private: int a; int b; }; A.cpp : #include "A.h" inline int A::max() { return a > b ? a : b; } Main.cpp : #include <iostream> #include "A.h" using namespace std; inline int A::max() { return a > b ? a : b; } int main() { A a(3, 5); cout<<a.max()<<endl; return 0; }
一切正常编译,输出结果:5
倘若你在Main.cpp中没有定义max内联函数,那么会出现链接错误:
error LNK2001: unresolved external symbol “public: int __thiscall A::max(void)” (?max@A@@QAEHXZ)main.obj一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!
- 另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行).
inline
对编译器来说只是一个建议,编译器完全可以不采纳这个建议。有些函数即使声明为内联的也不一定会被编译器内联。内联函数可以避免宏的边际效应。
#define SQUARE(X) ((X)*(X)); inline double square(double x){return x*x;} int c, d; c = d = 11; int e = SQUARE(c++); int f = square(d++); cout << "e = " << e << ", now c is" << c << endl; cout << "f = " << f << ", now d is " << d << endl; 输出的结果如下: e = 132, now c is13 f = 121, now d is 12
内联函数在Debug版中并没有真正的内联,所以可以调试。在Release版中才会被编译器内联。