Effective C++ 第三十条 Understand the ins and outs of inlining.

透彻了解 inlining 的里里外外
inline 的优点
Inline 函数是非常好的设计,既可以调用它们又可以不需要承受函数调用而导致的额外开销(如寄存器保存等)。编译器的优化机制通常就是浓缩“不含函数调用”的代码。但是 inline 也有副作用,就是增加目标代码的大小,具体如何请看下方实例:
如果 inline 函数有多条(也不能太多,太多的话编译器不会把其当作 inline 函数),代码就膨胀得很快。如果代码膨胀而造成程序体积过大,inline 会导致额外的内存换页(paging),降低指令还俗缓存装置的命中率(instruction cache hit rate)。
inline 的提出有两种,一种是隐式,一种是显式。隐式提出就是将函数定义在 class 内:
另一种是显式,如 case 1 中那样,函数用 inline 修饰。
但是要注意一点,inline 只是一种申请,并不是强制编译器要这么做,编译器可以不听。
inline 的缺点
Inline 函数通常被置于头文件内,因为大多数环境下进行编译,为了将函数调用替换为被调用函数的本体,是需要知道这个函数长什么样子的,否则无法完成替换。少数环境可以在运行期再进行替换,但是毕竟是少数。这就导致了大多数情况下,如果 inline 的函数本体有修改,所有涉及到该 inline 函数的整个文件需要重新编译,你应该听说过 C++ 大项目编译一次时间很长。
inline 函数无法设置断点,因为这个函数在执行过程中早就被替换为了函数本体,这个函数是不存在的,也就无法根据这个函数来设置断点。如果需要调试,只能在调试版程序中禁止发生 inlining。
inline 的注意点
inline 很多时候要和 template 一起使用,只有 template 下所有类型都需要被声明为 inline 才使用 inline ,否则就不该使用 inline。大部分编译器拒绝太过复杂的 inlining(比如带有循环和递归)。而且几乎所有对 virtual 函数的调用都会使得 inlining 落空。
即使编译器有意 inlining 某个函数,实际上还是需要为其生成一个函数本体,因为我们可能会在代码中使用到函数指针,如果没有这个函数本体,指向该函数的函数指针将为空,这不合理。