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

C++中的inline函数(内联函数)

前言:我们在C中学习宏的时候,就体会到了宏在编写的时候需要注意非常多的细节,否则会导致出错,而C++在设计的时候便为解决C语言在一些情况下不方便而提出了inline(内联函数)这一新特性

1 ADD宏函数

ADD函数宏的写法有以下四种:

  • 1 #define ADD(int a, int b) return a + b;
  • 2 #define ADD(a, b) a + b;
  • 3 #define ADD(a, b) (a + b)
  • 4 #define ADD(a, b) ((a) + (b))
    你觉得上面哪种是对的?我们一个一个的进行分析
1.1 #define ADD(int a, int b) return a + b;

我们首先要说明的是宏函数本质就是一种替换而不是函数,这样写在语法的层面上就是错误的
在这里插入图片描述

1.2 #define ADD(a, b) a + b;

在这里插入图片描述
所以我们一般定义宏函数的时候不在后面加;
并且注意在这个例子里面就算不加;也是一个错误的写法
在这里插入图片描述
按理来说我们希望得到的是(1+2)*(2+3)=15,那为什么结果是8呢?
还是要抓住宏函数就是一个替换的规则ADD(1,2)*ADD(2,3)被替换为1+2\*2+3=8,我们可以看出我们没有保证每一个ADD宏替换后的独立。

1.3 #define ADD(a, b) (a + b)

在这里插入图片描述
所以这个写法也是错误的,假如ab其中是一个表达式的话,这个宏函数的替换就会违背我们预想的逻辑。

1.4 #define ADD(a, b) ((a) + (b))

这样的写不仅保证了ADD宏函数的独立性而且保证了ADD宏函数参数ab的独立性,是一个正确的宏函数。

小结:我们可以看出写对一个宏函数要注意的细节还是很多的,一不留神就容易出现问题。但是宏函数能够在预处理阶段替换,不用建立函数栈帧,可以提效(提高效率),而我们C++inline就可以继承这些优点并且屏蔽实现细节

在回顾宏后,接下来我们正式进入inline函数的学习

2 inline(内联函数)

2.1 liline的基本概念和特征
  • inline修饰的函数就是内联函数
  • 编译阶段,编译器会将内联函数展开(类似于宏替换),这样函数就不会创建栈帧,从而提高效率
  • inline修饰的内联函数是否展开取决于编译器,inline修饰函数这是给编译器一个建议,并且不同编译器对内联函数展开情况各不相同,因为这是C++标准未定义的。

关于内联函数展开的说明:内联函数的展开就是在编译阶段,编译器会在这个位置直接插入函数代码(并不是原封不动的插入,要根据上下文逻辑进行必要的转换和适配,以保证代码语义的正确性)在这里插入图片描述
宏的实现需要我们自己去实现,而liline内联函数编译器帮助我们处理,但编译器又不是特别智能,它只能处理一些短小函数,对于代码较多的,递归函数即使加上inline也会被编译器忽略。

vs编译器下debug版本默认不展开inline,我们想要实现liline需要设置

2.2 vs设置inline选项

在这里插入图片描述
在这里插入图片描述
设置好后我们就可以通过汇编看内联函数非内联函数的区别了
普通add函数:
在这里插入图片描述
内联add函数:
在这里插入图片描述
我们可以明显看出在内联函数中inline没有创建函数栈帧,并且都被展开在main函数的cout << add(x, y) << endl;的这里,我们可以看到内联函数的这一块汇编代码明显比普通函数

2.3 inline声明和定义不能分离

inline声明和定义分离会产生链接错误,inline被展开其就没有函数地址,会在链接的时候出错

我们要理解这个,必须先简单的回顾下编译和链接的过程
在这里插入图片描述
F.h中有f1f2函数的声明,而在F.cpp中有这两个函数的实现,那我们要在Test.cpp文件中使用这两个函数涉及到什么过程呢?

  • 预处理:首先预处理将头文件F.h内容添加到两个cpp文件中。(预处理阶段还做了其它事)
  • 编译:检查语法生成汇编代码,这时候编译器已经将F.cpp中的f1f2函数编译并有其函数地址并记录在符号表中,而由于Test.cpp函数中只有两个函数的声明,所以使用这两个函数的位置编译的时候两个函数的地址并未填入(等待编译的时候补充)
  • 汇编:将汇编代码转化为二进制机器指令
  • 链接:将两个cpp的目标文件合并为.exe的可执行文件,这个时候Test.o(linux下)目标文件便去F.o符号表中找f1f2函数地址,以填补在汇编指令中call 指定函数地址空缺。

而被inline修饰的内联函数具有内部链接属性,它不会出现在符号表中,如果f1或者f2是内联函数那么Test.o就无法从符号表中获取函数地址从而找到函数完成调用,从而导致链接错误。

inline的内联函数一样,static修饰的函数也具有内部链接属性(函数只能在该文件使用,其它文件找不到)
在这里插入图片描述
extern可以声明函数的存在,从而让编译器不报错,并在后面的链接阶段从其它文件的符号表中去寻找函数地址,我们可以看到函数被正确使用。
static修饰后:
在这里插入图片描述

发生了链接错误,static将函数有外部链接属性变成内部链接属性

总结:符号表就是各个文件调用其它文件的说明书,而inlinestatic会将函数从这个说明书(符号表)去除,从而让文件无法使用其它文件的函数(就是不知道这个函数的地址)。

那内联函数这么好,我们是不是凡是个函数都给前面加inline变成内联函数呢?

答案当然是不可以,我们可以通过一个场景来看
在这里插入图片描述
inlinefunc函数被频繁的调用的话,每个位置都被展开,那么整个程序的代码量便会大大增加,会导致程序运行变慢。
所以我们一般将调用频繁且短小函数设置为内联函数。

http://www.dtcms.com/a/586817.html

相关文章:

  • 局域网内建网站电子商务网站建设asp sql 源码下载
  • 个人信息网站模板网站开发中如何实现gps定位
  • netcore 托管Redis服务
  • asp网站建设报告书手机网站欣赏
  • 网站建设功能描述书网站建设电话销售的话术
  • 测试用例的设计思路及方法
  • cms建站系统 开源劳务输送网站建设方案
  • 自建网站教程海宁市住房和城乡规划建设局网站
  • 静态网站更新c .net网站开发视频教程
  • 绍兴网站制作方案定制借贷网站开发是否合法
  • 上海优质网站seo有哪些seo优化推广工程师
  • 洛阳霞光建设网站网站公司怎么找客户
  • 公司网站能自己做二维码phpcms v9 网站建设设计制作网络科技模板
  • 每天一篇好文章网站专业网站建设哪个好
  • 赣州网站建设培训毕业设计做课程网站好
  • 8.基础--SQL--DDL-表操作-修改删除
  • Java 大视界 --Java 大数据在智能医疗远程手术机器人控制与数据传输中的技术支持
  • 格瑞特网站建设只能用域名访问WordPress
  • 巩义网站建设河北网站制作
  • 淘宝建设网站的理由上海小程序搭建
  • Java枚举类型详解:让你的程序更具表达力和可读性!
  • 网站开发公司怎么查电子商务网站设计分析怎么做
  • 住宅代理能用多久?其寿命影响因素与延长技巧
  • 网站后台数据库丢失郑州东区网站建设
  • ElfBoard技术贴|如何在【RK3588】ELF 2开发板进行GDB调试
  • 4.3.5【2017统考真题】
  • 推广qq群的网站seo推广排名平台有哪些
  • 建设网站前的目的什么叫H5网站开发
  • 网站建设丨选择金手指排名15抚州建设工程造价管理站网站
  • 河南网络洛阳网站建设河南网站建设百度一下百度首页登录