内联函数是一种编程语言结构,用来建议编译器对一些特殊函数进行内联扩展;也就是说建议编译器将指定的函数体插入并取代每一处调用该函数的地方(上下文),从而节省每次调用函数时带来的额外时间开支。1
使用内联函数时必须考虑程序的占用空间和执行效率。
C++中通过inline
修饰符来建议编译器生成内联函数。
在类声明中定义的成员函数,除了虚函数外,默认都是隐式地内联的。2
class A {
int Fun() { return 0; } //类内定义,隐式内联
}
class A {
int Fun();
}
// .cpp文件中
inline int A::Fun() { return 0; } // 类外定义,需显式内联
夹带着宏实参的函数式宏定义(Function-like Macro)是通过对文本直接替换的方式,同样是在调用处展开代码来避免函数调用的开销。
宏只做预处理而不编译,不会检查程序是否符合C语法。
函数式宏定义本身不必编译生成指令,但是代码中出现的每次调用所编译生成的指令都相当于一个函数体。
#define GET_MAX(a, b) ((a) > (b) ? (a) : (b)) //内外层括号都不可以省
int a = 5, b = 0;
GET_MAX(++a, b); //a被累加了两次
GET_MAX(++a, b + 10); //a被累加了一次
调用函数时先求实参表达式的值再传给形参,如果实参表达式有Side Effect,那么这些Side Effect只发生一次。但宏只是简单的文本替换,所以宏中的 a 都会被替换为 ++a 。由于 ++ a 比 b 大,所以第一个调用中的a会被累加两次。而 ++a 又比 b + 10 要小,所有第二个调用中的 a 只会被累加一次。文本替换难以做到与一般函数的行为一致。switch
语句的函数往往是得不偿失的。因为光循环和switch语句本身就有一定的代码量。C++17标准新加入了inline可用于修饰变量的规则5。不过不在内联函数范围内,有机会额外探讨。
wikipedia 内联函数 ↩︎
interview - C/C++ 技术面试基础知识总结 ↩︎ ↩︎ ↩︎ ↩︎
Effective C++ ↩︎ ↩︎
C++ 内联函数 | 菜鸟教程 ↩︎
inline specifier - cppreference.com ↩︎