C++内联函数详解
【摘要】 内联函数除了上面的内容,我们C++的祖师爷呢还觉得C语言中的宏也不是很好:我们在C语言的预处理那一章也有比较详细的学习过宏,也分析了宏的缺点:当然宏也是有一些优点的:比如我们定义一个宏函数(当然它不是一个真正的函数),它也可以完成一个函数的功能,但是呢它不用像真正的函数那样建立函数栈帧。补充:C++中建议用const和枚举enum代替宏定义的常量从宏的这些优缺点出发,C++又引入了一个新的概...
内联函数
除了上面的内容,我们C++的祖师爷呢还觉得C语言中的宏也不是很好:
我们在C语言的预处理那一章也有比较详细的学习过宏,也分析了宏的缺点:
当然宏也是有一些优点的:
比如我们定义一个宏函数(当然它不是一个真正的函数),它也可以完成一个函数的功能,但是呢它不用像真正的函数那样建立函数栈帧。
补充:C++中建议用const和枚举enum代替宏定义的常量
从宏的这些优缺点出发,C++又引入了一个新的概念——内联函数。
7.1 概念
那什么是内联函数呢?
以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率。
如果是定义一个普通的函数:
我们调试看它的汇编:
大家可能对汇编不太懂,但是看到这个call 函数名(地址)
其实就是去调用这个函数建立栈帧了。
那我们现在把它改成内联函数:
如果在上述函数前增加inline关键字将其改成内联函数,在编译期间编译器会用函数体替换函数的调用。
我们再来看一下反汇编:
怎么没起作用啊。
怎么样让它起作用呢?
🆗,它在release版本下面会起作用,或者在debug版本下需要我们进行一下设置:
然后我们再来看:
这次是不是就没有call Add那个指令了,说明我们的内联函数就起作用了,就没有函数调用建立栈帧的开销了。
7.2 内联函数的特性
inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用。
缺陷:可能会使目标文件变大,
优势:少了调用开销,提高程序运行效率。
简单解释一下:
这里说的这个空间换时间,不是说程序运行时占用的空间会变大,而是最终产生的可执行程序可能会变大。
因为C++编译器会在调用内联函数的地方将函数直接展开,这样的话与普通的调用相比,产生的指令就可能变多,所以最终生成的可执行程序可能会变大。
inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。
下图为《C++prime》第五版关于inline的建议:
也就是说:
不是所有的内联函数最终都会按照内联函数进行处理的,一般规模较小并且频繁使用的的我们才实现成内联函数,否则即使我们实现成内联函数,编译器也不一定会按照内联函数进行处理。
举个例子:
刚才的Add函数我们用inline修饰后调试发现确实按照内联函数处理了,那如果我们现在在Add函数中再多增加一些语句,有可能就不再按内联函数执行了:
我们再来调试观察一下:
是不是又有call Add了。
内联函数不能声明和定义分离,分离会导致链接错误
因为内联函数编译期间就会在函数调用的地方被展开,不会像普通的函数调用那样call一个地址然后跳转调用,就没有函数地址了(可以认为内联函数不会产生地址进符号表),这样链接的时候就会找不到。
所以内联函数如果有声明的话,把声明定义放一起。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)