1.什么是内联函数
简单来说,在 c 和 c + + 编程语言中,一个带有inline标识符的函数, 我们称其为inline函数。类似的函数标识符,还有virtual,explicit。
明白了这个定义之后,我们接下来解释一下为什么需要内联函数。
2.为什么需要内联函数
我们都知道,当程序执行 function call 指令时,CPU会存储函数调用后指令的地址,复制堆栈上函数的参数,最后将控制权转移给指定的函数。 然后当fuction call执行完之后,CPU再返回之前保存的下个操作指令,还原堆栈上的参数。 关键点就在这里,假如我们的函数的执行时间小于从调用方函数到被调用方函数(被调用方)的切换时间那么,这就是一种可观的额外开销,也就是我们常说的overhead。但是对于一些比较复杂的函数,函数调用花费的时间通常与函数运行所需的时间相比微不足道。
举个生活中的例子,假如你到淘宝买东西,对于一个9.9的物品,你购买它需要9.9,但是运费需要10元。这种情况下你可以接受这个运费的价格吗?但是你这个东西原价是500元,我想你很乐意多花10元的运费来购买它。
事实上,对于小型的、常用的函数,执行函数调用所需的时间通常远远超过实际执行函数代码所需的时间。所以这种情况下,C++提供内联函数,来减少我们所提到的额外的开销。
3.内联函数的行为及使用
内联函数是在调用时展开的函数。 当内联函数被调用时,内联函数的整个代码将插入或替换到内联函数调用的位置。 这种替换由 c + + 编译器在编译时执行。
你可以这样来简单的声明一个内联函数:
inline int add(int a, int b)
{
return (a + b);
}
记住,内联只是对编译器的一个请求,而不是命令。 编译器可以忽略内联请求,比如:
- 如果函数包含循环。(for,while,do-while)
- 如果函数包含静态变量
- 如果函数是递归的
- 如果函数返回类型不是 void,并且返回语句不存在于函数体中
- 如果函数包含 switch 或 goto 语句
也就是说,你当然可以对你的程序里的所有的函数都加上inline,但是最后到底in不inline,还要看编译器心情。
4.inline的优缺点
优点:
- 它避免了函数调用开销,从而加快了程序的执行速度
- 当函数调用发生时,它节省了堆栈上变量 push / pop 的开销
- 它还节省了函数返回调用的开销
缺点:
- 使代码臃肿,这个指的是你程序最后生成的二进制文件大小
- 内联函数可能会增加编译时间开销,如果有人改变内联函数中的代码,那么所有的调用位置都必须重新编译
- 内联函数可能对许多嵌入式系统没有用处。 因为在嵌入式系统中,代码大小比速度更重要
5.你还需要注意的
实际上,在C++中,类中定义的所有函数都是隐式内联的。 如果你需要在类中显式声明内联函数,那么只需在类中声明该函数,然后在类外用inline修饰它。 例如:
class A
{
void this_is_inline();
}
inline void A::this_is_inline()
{
//do something
}
而类似下面的代码,其实是一种不好的代码风格:
class A
{
// 多余的inline声明
inline void this_is_inline()
{
//do something
}
}