【C++】内联函数一看就懂?

在这里插入图片描述


个人主页 :阿然成长日记 点击可跳转
个人专栏: 数据结构与算法C语言进阶
不能则学,不知则问,耻于问人,决无长进

文章目录

  • 一、引入:
  • 二、内联函数概念
  • 三、修改属性
  • 四、实例
  • 五、内联函数的特性
  • 六、内联函数的优缺点
    • 1.优点:
    • 2.缺点:
  • 七、内联函数的使用细则

一、引入:

我们在C语言学习中学习了宏的相关知识,宏的定义:#define 机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义。通过宏定义的函数,在编译时,自动替换的函数调用位置,不会进行压栈等操作,可以提升效率,但是他的缺点也很明显,就是宏不支持调试的,也没有类型安全的检查,而且语法复杂。所以我们引进了内联函数。

二、内联函数概念

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

三、修改属性

  1. release模式下,查看编译器生成的汇编代码中是否存在call Add
  2. debug模式下,需要对编译器进行设置,否则不会展开,无法进行调试!(因为debug模式下,编译器默认不会对代码进行优化,以下给出vs2019的设置方式
    第一步:右击你创建的项目并点击属性
    【C++】内联函数一看就懂?_第1张图片
    第二步::点击常规–调式信息格式–修改为程序数据库

【C++】内联函数一看就懂?_第2张图片
第三步:点击优化–内联函数扩展–只适用于inline(/Ob1)

【C++】内联函数一看就懂?_第3张图片

四、实例

看一下代码:
定义了两个函数非内联函数Add1内联函数Add2。

int Add1(int left, int right)
{
	int ret1 = left + right;
	return ret1;
}

inline int Add2(int x, int y)
{
	int ret2 = x + y;
	return ret2;
}

int main()
{
	//非内联
	int recive1 = Add1(4, 5);
	//内联
	int recive2 = Add2(5, 7);
	return 0;
}

通过返汇编可以清楚的看到,内联函数的调用没有,push压栈等操作。
【C++】内联函数一看就懂?_第4张图片
绿色方框内是非内联函数调用:可以发现使用了push call操作。
蓝色方框是内联函数:直接mov移动过来,全程没有压栈,出栈操作。

五、内联函数的特性

  1. inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率
  2. inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。
  3. inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。

六、内联函数的优缺点

1.优点:

  • 不需要建立函数栈帧。
  • 可读性强,且不易出错。
  • 可以调试
  • 使用起来简单。

2.缺点:

内联不是万能的,它以代码膨胀(拷贝)为代价,仅仅省区了函数调用的开销,从而提高程序的执行效率。(开销指的是参数的压栈、跳转、退栈和返回操作)。

七、内联函数的使用细则

(1)如果执行函数体内代码的时间比函数调用的开销大得多,那么inline效率收益会很小。
(2)每一处内联函数的调用都要拷贝代码,使程序的总代码量增大,消耗更多的内存空间。
(3)以下情况不宜使用内联:

  • 如果函数体内代码比较长,使用内联将导致可执行代码膨胀过大。
  • 如果函数体内出现循环或者其他复杂的控制结构,那么执行函数体内代码的时间将比函数调用的开销大得多。

总之:一般只将那些短小的、频繁调用的函数声明才使用内联函数。

你可能感兴趣的:(C++基础,c++,开发语言)