当前位置: 首页 > news >正文

【C++】初阶 --- 内联函数(inline)

在这里插入图片描述

文章目录

  • 🥞内联函数
    • 🍟1、C语言实现"宏函数"
    • 🍟2、内联函数的概念
    • 🍟3、内联函数的特性
    • 🍟4、总结

在这里插入图片描述

🥞内联函数

🍟1、C语言实现"宏函数"

🥰用C语言先来实现普通的Add函数看一下👇

int Add(int left, int right)
{return left + right;
}int main()
{int ret = 0;ret = Add(1, 2);return 0;
}

转到反汇编来看一下:
在这里插入图片描述

可以看到,编译器为了实现一个简单的相加函数,Add函数体内需要执行的汇编指令要很多,而且为了调用函数还要执行指令跳转(并且要在栈区上为函数开辟栈帧空间),如果Add函数被重复大量地使用,则会消耗很大一部分系统性能。因此C语言中为了提高程序的运行效率,对于类似的简单函数(注意仅限于非递归且简短的函数),我们常使用宏来替代:

实现一个Add宏函数:

//实现一个Add的宏函数
#define Add(x, y) ((x)+(y))int main()
{int ret = 0;ret = Add(1, 2);cout << ret << endl;return 0;
}

🚩宏的作用相当于代码语句的替换,上面代码段中的宏,是把Add(x, y)形式的语句替换成((x)+(y)),这种替换的过程是在预处理的阶段完成的

使用宏替换后,再次转到反汇编来看一下:
在这里插入图片描述

可见使用宏代替那些简短的非递归(且会被大量使用)的函数可以一定程度上提高程序的性能
但是由于宏的本质是代码替换,所以有时候会让代码变得混乱难以维护,而且宏本身的使用容易出错,C++就提供了一种类似的语法机制 — “内联函数”来代替宏

🍟2、内联函数的概念

inline关键字修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方(call指令处)将被调函数展开成一系列汇编指令并在主函数的栈帧空间中实现被调函数的功能(类似于宏替换,但不是在预处理的阶段完成的),系统无需为被调函数建立函数栈帧,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率

用之前的例子举例说明,使用inline修饰Add函数
在这里插入图片描述

使用inline修饰Add函数
在这里插入图片描述
可见系统并没有为inline Add函数建立函数栈帧,也没有执行任何指令跳转,程序性能有所提升。(但是注意,Add函数的函数体(包含其指令段)依然被原模原样地存放在只读常量区,只是编译器在编译时将函数体中必要的指令“搬”到了主函数的指令段中取代了call指令)

🍟3、内联函数的特性

  1. inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用
    🔴缺陷:可能会使目标文件变大(汇编指令是要占内存的,编译器用一系列指令段替换call指令会使文件的总指令条数增加)
    🔴优势:少了调用开销,提高程序运行效率
  1. inline对于编译器而言只是一个建议,而不是要强制执行的命令,不同编译器关于inline实现机制可能不同,一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。下图为《C++prime》第五版关于inline的建议:
    在这里插入图片描述

3. inline内联函数不建议声明和定义分离(只用定义即可,定义本身也是一种声名),分离会导致链接错误因为inline被展开,因为使用inline,调用函数时call指令被替换了,没有call指令,链接器就链接不到函数体的指令段了

// F.h
#include <iostream>
using namespace std;inline void f(int i);// F.cpp
#include "F.h"void f(int i)
{cout << i << endl;
}// main.cpp
#include "F.h"int main()
{f(10);return 0;
}

在这里插入图片描述

🍟4、总结

🦀宏的优缺点:

🚩优点:
1.增强代码的复用性
2.没有类型的严格限制
2.提高性能

🚩缺点:
1.不方便调试宏(因为预编译阶段进行了替换)
2.导致代码可读性差,可维护性差,容易误用(语法坑很多)
3.没有类型安全的检查

🦀内联函数的优缺点:

🚩优点:
1.inline定义的内联函数,函数代码被放入符号表中,在使用时进行替换(像宏一样展开),不需要建立栈帧,效率很高
2.类的内联函数也是函数。编绎器在调用一个内联函数,首先会检查参数问题,保证调用正确,像对待真正函数一样,消除了隐患及局限性
3.inline可以作为类的成员函数,也可以使用所在类的保护成员及私有成员

🚩缺点:
1.内联函数以复制为代价,活动产函数开销
2.如果函数的代码较长,使用内联将消耗过多内存(较长不建议使用!)
3.如果函数体内有循环,那么执行函数代码时间比调用开销大(有循环不建立使用!)

😍这期内容比较容易理解,希望烙铁们能理解消化,有所收获哦!

总结🥰
以上就是 【C++】内联函数 的全部内容啦🥳🥳🥳🥳
本文章所在【C++初阶】专栏,感兴趣的烙铁可以订阅本专栏哦🥳🥳🥳
前途很远,也很暗,但是不要怕,不怕的人面前才有路。💕💕💕
小的会继续学习,继续努力带来更好的作品😊😊😊
创作写文不易,还多请各位大佬uu们多多支持哦🥰🥰🥰

请添加图片描述

http://www.lryc.cn/news/111532.html

相关文章:

  • VGGNet剪枝实战:使用VGGNet训练、稀疏训练、剪枝、微调等,剪枝出只有3M的模型
  • 【iOS】GCD深入学习
  • Webpack开启本地服务器;HMR热模块替换;devServer配置;开发与生成环境的区分与配置
  • opencv 31-图像平滑处理-方框滤波cv2.boxFilter()
  • Kubernetes关于cpu资源分配的设计
  • Flink读取mysql数据库(java)
  • 小程序学习(五):WXSS模板语法
  • 注解 @JsonFormat 与 @DateTimeFormat 的使用
  • Python实现决策树算法:完整源码逐行解析
  • Linux文本三剑客---grep、sed、awk
  • 局域网VoIP网络电话测试
  • el-table 去掉边框(修改颜色)
  • redis与MongoDB的区别
  • CSS设置高度
  • 开源免费用|Apache Doris 2.0 推出跨集群数据复制功能
  • 【docker】docker-compose服务编排
  • EdgeBox_tx1_A200 PyTorch v1.9.0 环境部署
  • 【雕爷学编程】MicroPython动手做(33)——物联网之天气预报
  • 分库分表之基于Shardingjdbc+docker+mysql主从架构实现读写分离 (三)
  • 探秘企业DevOps一体化平台建设终极形态丨IDCF
  • 百度智能创做AI平台
  • Python 开发工具 Pycharm —— 使用技巧Lv.1
  • zookeeper --- 高级篇
  • TypeScript【enum 枚举】
  • SpringBoot项目增加logback日志文件
  • 复习之selinux的管理
  • 无涯教程-Lua - 文件I/O
  • java+ssm民宿酒店客房推荐预订系统_2k78b--论文
  • Docker实战-关于Docker镜像的相关操作(一)
  • Jenkins Gerrit Trigger实践