C++专题:内联函数 vs. 宏定义

一.区别

  本质上,宏定义就是纯粹的文本替换,而内联函数是函数,其执行结果与普通函数调用是一致的。

  • 编译阶段:宏定义是在预编译阶段展开的,内联函数是在编译阶段展开。
  • 传参方式:内联函数是按值传递参数,跟普通函数别无二致,宏定义不能按值传递
  • 二义性:宏定义容易出现二义性的问题,内联函数不存在这种问题

二.举例说明

(一)传参

  1. 宏定义
#include <iostream>
using namespace std;

#define SQUARE(X) ((X)*(X))

int main()
{
	int a = 1;
	cout<< SQUARE(a++) << endl;
	cout<< a << endl;
	return 0;
}

编译告警:

define.cpp:9:17: warning: multiple unsequenced modifications to 'a' [-Wunsequenced]
        cout<< SQUARE(a++) << endl;
                       ^~
define.cpp:4:21: note: expanded from macro 'SQUARE'
#define SQUARE(X) ((X)*(X))
                    ^   ~
1 warning generated.

输出结果:

2
3

分析如下:SQUARE(a++) 被展开为((a++)*(a++)),执行了两次自增操作,最终结果是2,a的值变为3

  1. 内联函数
#include <iostream>
using namespace std;

inline int square(int x) { return x * x; }

int main()
{
	int a = 1;
	cout<< square(a++) << endl;
	cout<< a << endl;
	return 0;
}

输出结果:

1
2

分析如下:符合预期

(二)二义性

  1. 宏定义
#include <iostream>
using namespace std;

#define SQUARE(X) X*X

int main()
{
	cout<< SQUARE(1 + 1) << endl;
	return 0;
}

输出如下:

8

分析如下:从语义上理解是SQUARE(1+1)的值为4。实际上,SQUARE(1 + 1)展开为1+1*1+1,结果是3

  1. 内联函数
#include <iostream>
using namespace std;

inline int square(int x) { return x * x; }

int main()
{
	cout<< square(1+1) << endl;
	return 0;
}

输出结果:

4

分析如下:符合预期,内联函数有完整的函数语义,不会出现二义性

三.注意事项

  • 对于体积小且频繁调用的函数,可以定义为内联函数。
  • 内联函数一般定义在头文件,编译器需要在编译阶段找到其完整定义。
  • 内联函数之所以能提高性能是在于,函数本身的执行时间小于函数调用的开销,我的理解是本质上是空间换时间。
  • 内联函数的定义只是程序员的一种请求,编译器并不一定会满足要求。比如函数体存在递归调用或者体积过大,那么编译器会将其视为普通函数。
  • 在C++中,在类内定义的成员函数默认是内联函数,内联函数不可以定义为虚函数(可以思考下为什么?)。
posted @ 2020-11-21 15:49  Jgirl  阅读(445)  评论(0)    收藏  举报