前言
今天小编给大家带来的是内联函数的介绍,大家可能之前没有听过内联函数这个名词,那么今天就和小编一起认识一下这个朋友吧。
内联函数
我们每次在调用函数时都会开辟一个函数栈帧,那么过度的函数栈帧的开辟就会导致栈满崩溃的情况,也会在一定程度上影响程序调用的效率,那么我们接下来介绍的东西就是解决此类问题的。
1. 概念
以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调
用建立栈帧的开销,内联函数提升程序运行的效率。
那么我们要如何观察到此类情况,这里需要我们简单的去了解一下汇编的部分代码,这里小编在后续的文章中会给大家简单介绍一下,这里大家就简单的跟着小编的步伐理解一下
首先我们需要知道一点,我们在调用函数时我的会产生call 对应函数名,由于C语言在window下函数的修饰规则比较简单,所以这里我们这里用C语言给大家演示:
#include<stdio.h> int Add(int a, int b) { int c = a + b; return c; } int main() { int ret = Add(1, 2); return 0; }
这里我们看到此处产生的反汇编代码:
很明显这里我们产生了call指令。
那么如果我们这里用内联函数修饰后,我们只需要关注该是否产生call指令的调用指令。
但是由于我们在默认的debug模式下,inline不会起作用,否则就不方便调试了,所以在查看之前我们需要进行一些设置,这里有两种查看方式如下:
1. 在release模式下,查看编译器生成的汇编代码中是否存在call 函数明
2. 在debug模式下,需要对编译器进行设置,否则不会展开(因为debug模式下,编译器默认不
会对代码进行优化)
那么我们具体设置方法如下:
首先右击项目名,我们就会出现如下界面,然后点击属性
然后就会出现如下界面:
这里我们点击C/C++,看到常规后将调试信息格式改为程序数据库,然后我们点击优化,把内联函数扩展改为只适用于_inline(/Ob1),即可。
最后点击应用就完成了我们的配置,然后接下来小编就给大家演示一下添加内联函数产生的效果:
#include<iostream> using namespace std; inline int Add(int a, int b) { int c = a + b; return c; } int main() { int ret = Add(1, 2); return 0; }
那么这里我们看到反汇编代码:
我们这里明显没有看到,call调用函数的指令,所以我们可以看到这里的内联函数的确是被展开了。
2.特性
1. inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会
用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运
行效率。
这里我给大家简单的讲解一下:
这里我们假设该函数编译后的指令是50行,假设有10000个位置调用该函数,那么不使用内联函数我们这里调用产生的指令是每次调用的指令和该函数指令,所以就是10000+50行,但是使用内联函数后就是10000*50行,这样就会导致可执行程序变大。
2. inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建 议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不 是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性
3. inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到(也就是inline被展开后函数就不会进符号表,链接时就找不到该符号)