C++ 内联函数

C++ 内联函数·

C++中支持内联函数,其目的是为了提高函数的执行效率,用关键字 inline 放在函数定义的前面(注意是定义而非声明)即可将函数指定为内联函数,内联函数通常就是将它在程序中的每个调用点上“内联地”展开。

内联函数有效地提高函数的执行效率,如果写成函数有一个潜在的缺点:调用函数比求解等价表达式要慢得多。在大多数的机器上,调用函数都要做很多工作:调用前要先保存寄存器,并在返回时恢复,复制实参,程序还必须转向一个新位置执行。

描述·

C++ 内联函数是通常与一起使用。如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。

对内联函数进行任何修改,都需要重新编译函数的所有客户端,因为编译器需要重新更换一次所有的代码,否则将会继续使用旧的函数。

如果想把一个函数定义为内联函数,则需要定义函数时在函数名前面放置关键字 inline,在调用函数之前需要对函数进行定义。如果已定义的函数多于一行,编译器会忽略 inline 限定符。

在类定义中的定义的函数都是内联函数,即使没有使用 inline 说明符。

注意:

1.在内联函数内不允许使用循环语句、switch和开关语句
2.内联函数的定义必须出现在内联函数第一次调用之前(也就是使用这个函数之前);
3.类结构中所在的类说明内部定义的函数(有函数体)默认是内联函数。
在类里面声明的函数(不包含函数体,函数体在类外面)不是默认内联函数

提示:·

  • 只有当函数只有 10 行甚至更少时才将其定义为内联函数.

  • 定义: 当函数被声明为内联函数之后, 编译器会将其内联展开, 而不是按通常的函数调用机制进行调用.

  • 优点: 当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.

  • 缺点: 滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。

  • 结论: 一个较为合理的经验准则是, 不要内联超过 10 行的函数. 谨慎对待析构函数, 析构函数往往比其表面看起来要更长, 因为有隐含的成员和基类析构函数被调用!

  • 另一个实用的经验准则: 内联那些包含循环或 switch 语句的函数常常是得不偿失 (除非在大多数情况下, 这些循环或 switch 语句从不被执行).

  • 有些函数即使声明为内联的也不一定会被编译器内联, 这点很重要; 比如虚函数和递归函数就不会被正常内联. 通常, 递归函数不应该声明成内联函数.(递归调用堆栈的展开并不像循环那么简单, 比如递归层数在编译时可能是未知的, 大多数编译器都不支持内联递归函数). 虚函数内联的主要原因则是想把它的函数体放在类定义内, 为了图个方便, 抑或是当作文档描述其行为, 比如精短的存取函数.

实例·

1
2
3
4
5
6
7
8
inline int max(int a, int b)
{
return a > b ? a : b;
}
则调用: cout<< max(a, b) <<endl;

在编译时会展开为: cout<< (a > b ? a : b) <<endl;
从而消除了把 max写成函数的额外执行开销

关键字 inline 必须与函数定义体放在一起才能使函数成为内联,仅将 inline 放在函数声明前面不起任何作用。声明与定义不可混为一谈

1
2
3
4
5
6
7
8
9
10
11
如下的函数 Foo 不能成为内联函数:

inline void Foo(int x, int y); // inline 仅与函数声明放在一起
int main(){...}
void Foo(int x, int y){...}

而如下风格的函数 Foo 则成为内联函数:

void Foo(int x, int y);
int main(){...}
inline void Foo(int x, int y){...} // inline 与函数定义体放在一起