C++内联函数 inline

1.内联函数的概念:

inline修饰的函数叫做内联函数编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率

展开:编译器将相关内联函数的功能语句识别后放到相应位置。

类似与宏的替换,其实是宏的改进。

内联函数的定义格式:在函数的返回类型前加inline

inline int ADD(int x, int y)
{
	return x + y;
}

int main()
{
	int a = 6, b = 6;
	cout << ADD(a, b) << endl;
	return 0;
}

2.内联函数相比于宏的优越性:

C语言中的宏其实是很坑的,因为它极其容易写错,就比如说写一个最简单的ADD函数,请问以下哪个宏是对的?

实际上全都错了,第三个看起来是不是很像对的?其实在特定情况下也是错的:

输出的结果为22,这是因为加法的优先级在按位与按位或之前,所以会把中间的a和b加起来,结果自然就出错了,答案应该是:

#define ADD(x,y) ((x)+(y))

但是在内联中就不存在这样的问题了,因为内联不是单纯的替换,它是有传参的,所以内联相较于宏来说不容易出错。

归纳如下:

宏的缺点:

1.容易出错

2.不能调试

3.没有安全类型的检查(因为是直接替换)

而内联规避了这些缺点

3.内联函数的特性: 

(1)inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率。

(2)inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现、不是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。 

也就是说,即使你写的是内联函数,但是编译器认为这个函数不适合作为内联,那么这个函数就会被忽略掉内联特性。

以下为 《C++prime》第五版关于inline的建议:一般来说,内联机制用于优化规模较小、流程直接、频繁调用的函数。很多编译器都不支持内联递归函数,而且一个75行的函数也不大可能在调用点内联地展开。

(3)inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。

4.内联函数的使用和拓展:

我们先定义一个头文件,里面写上ADD函数的声明并注明它是一个内联函数。

接着在源文件add中写下ADD函数的定义 

最后在test.cpp文件中调用 

点击编译,发现报了个链接错误。 

这里验证了3.3内联函数不推荐声明和定义分离,接着我们添加一个func函数,由func函数间接调用ADD函数。

结果发现编译通过了:

为什么呢?我们首先要知道什么是链接错误,通俗来说链接错误就是编译器在运行到调用函数操作时,找不到这个函数,就会报链接错误。因为我们将ADD函数设置为内联函数,所以编译器就会认为这个内联函数在用的地方就直接展开了就没有必要生成ADD函数的指令和建立栈帧并将地址及其符号放入符号表,那么既然编译器都不生成指令和地址了,而这种定义和声明分开的操作并不会展开这个内联函数,因为头文件中只有声明,而定义在另一个文件中,从声明到定义也需要链接操作,链接操作需要地址及其符号。于是乎,从声明到定义的链接操作就出了问题,因为不生成地址了又怎么能找得到ADD函数的定义呢?

后面我加入了一个func函数间接调用ADD,因为ADD函数的定义和func函数的定义在一个文件中,编译器将视为内联函数的ADD直接在func中展开,就能正常编译了。

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值