写在前面
参考:
Effective C++ Item30
Inside the C++ Object Model 4.5 inline Functions
事实上现代的 C++编译器已经可以智能优化代码了, 并不需要 inline 来刻意处理了, 这里只是为了学习这种历史遗留下来的优化方法以及 inline 的一些可能会失效的情况.
inline 的处理
第一阶段:
分析函数定义, 以决定函数的本质 inline 能力(与编译器相关的能力)
如果函数因为复杂度等原因不能恒伟内敛, 就会被转为一个 static 函数, 并在’被编译模块’内产生对应的函数定义.
第二阶段
真正的 inline 函数扩展操作是在调用的那一点上, 这会带来参数的求值操作以及临时性对象的管理
适用场景
函数体较短
inline
int my_max(int a, int b) { return b > a ? b : a; }
相当于是宏的一种替代, 安全的实现.
不适用场景
递归函数
即使声明为inline, 也不会展开:
inline
int my_gcd(int a, int b) { return b ? my_gcd(b, a / b) : a; }
void t1(){
my_gcd(1,3);
my_gcd(12,30);
}
通过函数指针调用
不知道调用的是哪个函数, 情况和虚函数类似.
inline 内有局部变量
局部变量:
inline
int my_max(int a, int b) {
int tmp = b > a ? b : a;
return tmp;
}
此时如果被扩展多次, 就会产生多个局部变量.
inline 传入某些形式参数
这样会导致形式参数导入临时对象(这是为了避免重复求值), 造成资源浪费
inline
int my_max(int a, int b) { return b > a ? b : a; }
maxval = my_max(foo(), bar() + 1); // 临时对象
// 被展开为:
int t1, t2;
maxval = (t1 = foo()),
(t2 = bar() + 1),
t2 > t1 ? t2 : t1;
inline 函数内
不要嵌套声明 inline , 造成 inline 函数无法展开的问题. 有点类似递归函数.
函数体较大
这个不用多说了, 如果内联这样的函数会造成代码膨胀.
声明为虚函数
运行期才知道具体执行哪份代码, 所以inline不会在编译期被展开.
构造和析构函数
可能存在异常处理以及展开等情况, 尤其是继承情形. 这时候也不会内联展开