前言
内联函数与普通函数的区别是什么?
内联函数与宏还有关系?
内联函数与普通函数的区别
见下图,内联函数是为了增快程序运行速度所做的一项改进。说的更直接一些,它是以空间来换时间。常规函数执行到函数调用指令时,程序将在函数调用后立即存储该指令的内存地址,并将函数参数复制到堆栈(为此保留的内存块),跳到标记函数起点的内存单元,执行函数代码(也许还需将返回值放入到寄存器中),然后跳回到地址被保存的指令处。这里作者给了一个很恰当的比喻,这与阅读文章时停下来看脚注,并在阅读完脚注后返回到以前阅读的地方类似。
内联函数则在编译期间就被内联起来,并不需要函数的跳转。原因是编译器会为内联函数创建多个副本。

内联函数与宏的区别
看到上面的图右侧,我们会很自然的联想到宏。宏也是在编译期间被创建多个副本。但是内联函数跟宏还是有一些区别。
看下面的例子:计算平方。
使用内联函数和宏计算平方的范例
#include <iostream>
inline double square(double x) {
return x * x;
}
int main() {
using namespace std;
double a, b;
double c = 13.0;
a = square(5.0);
b = square(4.5 + 7.5); // can pass expressions
cout << "a = " << a << ", b = " << b << "\n";
cout << "c = " << c;
cout << ",c squared = " << square(c++) << "\n";
cout << "Now c = " << c << "\n";
return 0;
}
这里的输出结果是:
a = 25, b = 144
c = 13,c squared = 169
Now c = 14
如果我们直接把这个内联函数换成宏会发生什么呢?
#include <iostream>
#define square(x) x * x
int main() {
using namespace std;
double a, b;
double c = 13.0;
a = square(5.0);
b = square(4.5 + 7.5); // can pass expressions
cout << "a = " << a << ", b = " << b << "\n";
cout << "c = " << c;
cout << ",c squared = " << square(c++) << "\n";
cout << "Now c = " << c << "\n";
return 0;
}
a = 25, b = 45.75
c = 13,c squared = 182
Now c = 15
我们会看到 b, c squared 的值都错了。而 Now c 的值也发生了变化。
先来看 b 为什么会错,我们将 b = square(4.5 + 7.5) 展开会看到如下写法:
b = 4.5 + 7.5 * 4.5 + 7.5
这个跟我们的初衷
b = (4.5 + 7.5) * (4.5 + 7.5)
是不相符的,不过我们可以通过修改宏定义来解决
#define square(x) (x) * (x)
此时能够得到正确的值: b = 144
再来看 c squared 和 Now c。我们将 square(c++) 展开会看到如下写法:
(c++) * (c++)
在执行第一个 c++ 后,得到的值是 13,c 的值变成了 14,在执行到第二个 c++ 后,得到的值是 14,c 的值变成了 15,然后再将 13 * 14,因此 c squared 最终值是 182。而 c 最终值是 15。
这个结果与得到 c++ 的平方并且 c 递增一次的预期不相符。
结论
内联函数和常规函数一样,也是按值来传递参数。而宏则是由编译器直接展开。因此两者有着比较明显的区别。
作者在这里也提出,如果使用了宏,则需要考虑使用内联函数进行替换。