内联函数取代宏
宏
宏可以提高代码效率,宏不仅能将一个符号定义成一个值,比如#define N 10
,还可以定义一段代码。正常函数调用需要申请空间、将函数参数压入桟中、生成汇编语言的CALL、返回参数、执行汇编语言的RETURN等一系列操作。而宏只是利用预处理器完成文本替换,然后才经编译器编译,可以看成一段代码只不过用名字替代了,所以不存在函数调用。例如
#define f(x) x*x;
#include <iostream>
using namespace std;
void main()
{
cout << f(2) << endl;
}
这里输出结果为4,宏定义将f(x)定义为xx,在预处理阶段,会将代码f(2)替换为22,然后由编译器编译执行。
宏的弊端
虽然宏可以提高代码的效率,但是由于是简单地文本替代很容易出现错误,而且很难发现错误。例如:
#define f(x) x*x;
#define F(x) (x)*(x)
#include <iostream>
using namespace std;
void main()
{
int a = 1
cout << f(a+1) << endl;
cout << F(a++) << endl;
}
显然f(a+1)执行的结果不符合预期这是因为简单替换后为a+1a+1,与(a+1)(a+1)是不一样的。想要实现可以用F(a+1),但是F(x)依然有不能完成的任务,比如F(a++),期望结果为输出1,a变为2,但是结果是输出2,a变为3,这是因为a++执行了两次。
除了能够产生很多错误外,更主要的弊端是不能访问类里的数据成员。这也是c++中用内联函数取代宏的主要原因。
内联函数
-
内联函数的编译器原理:
内联函数在编译时首先编译器会将函数类型添加到符号表中,然后会对函数体进行分析检查,正确的话会将函数体的源程序或者编译后的指令也放入符号表中,这取决于编译器。当内联函数调用时,编译器会首先检查参数是否符合或者能否转换成正确类型,如果符合就就会有内联函数代码替换掉函数调用。由于仍然是函数调用的传参形式只不过执行方式变化,所以解决了宏定义的a++执行两次的情况。 -
语法
inline int f(int x){return x*x;}
应用内联函数可以提高代码效率,但是也要注意应用的场景。需注意以下几点
- 内联函数必须直接定义,纯粹的声明加上inline关键字没有任何效果。
- 在类的内部定义的函数都是内联函数,即使没有加上inline关键字也是。但是为了避免代码混乱一般都是将定义写在类外面,如果需要是内联函数在定义时加上inline关键字。
- 内联函数适合小函数的替换,如果是大函数用内联函数不仅不能提高效率还会消耗大量内存,使程序变长。
- 在编译器中只有在声明结束后才会进行内联函数,所以可以不用考虑顺序问题,即使内联函数用到的是后面声明的代码也可以。