【C++】内联函数

前言

在C语言中,我们学习过宏的用法。宏通常被用于进行简单的文本替换来执行一系列的操作,比如一些简单的运算。使用宏可以避免函数调用时建立栈帧的开销,提高程序的性能。我们首先来写一个实现加法功能的宏:

#define ADD(x, y) ((x) + (y))
int main()
{int a = 10;int b = 20;cout << ADD(10, 20) << endl;return 0;
}

这个宏完美实现了我们的加法需求,但在定义宏时需要格外小心,因为宏可能存在潜在的问题,如副作用和作用域。为确保宏替换后的正确性,可能需要加上多个括号,这样就比较繁琐。而且宏无法进行类型检查,因为它只是完成替换功能。为了解决这些问题,C++引入了内联函数,提供了一种更安全、清晰且性能保持良好的替代方案。


概念

用 inline 修饰的函数叫做内联函数,编译时C++编译器会视情况在调用内联函数的地方展开,此时同样没有函数调用建立栈帧的开销,因此可以提升程序运行的效率。现在我们将上面定义的宏改写成内联函数:

inline int Add(int x, int y)
{return x + y;
}int main()
{int a = 10;int b = 20;int ret1 = Add(10, 20);return 0;
}

写成内联函数后,我们就不需要像定义宏一样注意括号的细节了。我们转到反汇编来看一下: 

我们发现它并没有展开,而是和普通的函数调用一样,也建立了栈帧,因为这里依旧有 call 指令,原因是在 debug 模式下需要手动对编译器进行设置才能展开,而 release 模式下则不需要,但是 release 模式下无法调试,我们也无法看到展开的效果,因此接下来我们先设置下编译器。 

右键单击箭头指向的这个位置。

如图所示,选择程序数据库这一选项。

内联函数扩展这里选择只适用于 _inline 这一选项,然后点击确定,这样就设置好了。这时候我们在调试一次,转到反汇编来看:

可以看到 call 指令已经没有了,函数确实是直接展开了。并且内联函数下我们依旧可以对程序进行调试。这里有一个小细节,mov 指令是先针对左操作数也就是10的,而对于普通的函数调用,在建立栈帧时先压入栈中的是右操作数,如果不清楚的话可以往上回顾一下没展开的那段汇编代码。我们再来看看宏的汇编代码:

显而易见宏是不一样的,因为它是直接进行替换的。宏替换后只有这样这样一句语句,显然无法进行调试。 


特性

1. 内联是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段就会用函数体替换函数调用。这样可以省去调用函数的开销,提高程序的运行效率。但是事物总是具有两面性的,内联函数也会存在缺陷,如可能会使目标文件变大,就算内联函数本身很短,但是在调用了很多次的情况下会有很多次的展开,总代码行数就会变长了。

2. 内联对于编译器而言只是一个建议,是否采纳这个建议的决定权在于编译器。不同编译器关于内联的实现机制可能不同。一般建议将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现,一般10行左右是一个界限)、不是递归、且频繁调用的函数采用 inline 修饰,否则编译器会忽略内联建议。不可能把一个100行代码的函数当成内联对吧,否则多次调用的情况下目标文件岂不是非常的大。

3. 建议不要将内联函数的声明和定义分离,这样可以避免其他源文件在使用该函数时发生链接错误。由于内联函数在调用时会直接被展开,其函数地址不会进入符号表,导致在链接阶段无法找到该函数的地址。因此,如果一定要将内联函数的声明和定义分开,那么该内联函数只能在包含其定义的源文件中使用。


潜在面试问题

宏的优缺点:

优点:
1.
提高代码的复用性,通过简单的文本替换实现通用功能。
2. 在一些情况下,宏能够
提高程序的性能

缺点:
1. 宏
不便于调试,因为宏在预编译阶段就进行了替换,因此难以在调试中观察。
2. 可能导
致代码可读性和可维护性下降,并且容易被误用。
3.
缺乏类型安全的检查,可能导致错误的使用。

C++中用什么替代宏:

1. 常量的定义可以使用 const 或 enum 来替代宏,提高类型安全和可读性。
2. 短小函数的定义可以
使用内联函数来替代宏,这样不仅保障了性能,还避免了宏可能引入的潜在问题,并提高了代码的可维护性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/621426.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【我的RUST库】get_local_info 0.2.2发布

0.2.2增加在cargo上的github链接&#xff0c;地址&#xff1a; get_local_info - crates.io: Rust Package Registry

物理学如何推动生成式 AI 的发展

一、说明 许多尖端的生成式 AI 模型都受到物理学概念的启发。在本指南中&#xff0c;我们将从高层次上了解物理学如何推动人工智能的进步。不同的领域经常交叉授粉重要概念&#xff0c;这有助于推动其进步。数学概念为物理学的进步奠定了基础;物理学中的概念经常启发经济学的框…

紫外加速老化试热冲击试验箱

紫外加速老化试热冲击试验箱是用于测试产品在高低温环境下的适应性以及性能表现的实验设备。其功能特点主要包括以下几个方面&#xff1a; 1. 温度控制&#xff1a;冷热冲击试验箱能够提供高温、低温以及常温的测试环境&#xff0c;并且可以快速地实现温度的转换和控制。这使得…

高效办公:如何通过在文件名称右边添加关键字提升工作效率

在繁忙的办公环境中&#xff0c;经常要处理大量的文件和资料。那如何管理和查找这些文件呢&#xff0c;常见的方法有在文件名称右边添加关键字。下面来看云炫文件管理器如何通过在文件名称右边添加关键字来提升工作效率。 在文件名称右边添加关键字前后效果图。 文件名批量添加…

老卫带你学---leetcode刷题(38. 外观数列)

38. 外观数列 问题 给定一个正整数 n &#xff0c;输出外观数列的第 n 项。 「外观数列」是一个整数序列&#xff0c;从数字 1 开始&#xff0c;序列中的每一项都是对前一项的描述。 你可以将其视作是由递归公式定义的数字字符串序列&#xff1a; countAndSay(1) “1” c…

P5461 赦免战俘题解

题目 现有2n2n(n≤10) 名作弊者站成一个正方形方阵等候kkksc03的发落。kkksc03决定赦免一些作弊者。他将正方形矩阵均分为4个更小的正方形矩阵&#xff0c;每个更小的矩阵的边长是原矩阵的一半。其中左上角那一个矩阵的所有作弊者都将得到赦免&#xff0c;剩下3个小矩阵中&…

AC修炼计划(AtCoder Beginner Contest 334)A~G

传送门&#xff1a;UNIQUE VISION Programming Contest 2023 Christmas (AtCoder Beginner Contest 334) - AtCoder A题是最最基础的语法题就不再讲解。 B - Christmas Trees 该题虽然分低&#xff0c;但我觉得还是很不错的。 给你 l 和 r &#xff0c;设满足题意的数字是x则…

检查是否是类的对象实例

说在前面 &#x1f388;不知道大家对于算法的学习是一个怎样的心态呢&#xff1f;为了面试还是因为兴趣&#xff1f;不管是出于什么原因&#xff0c;算法学习需要持续保持。 题目描述 请你编写一个函数&#xff0c;检查给定的值是否是给定类或超类的实例。 可以传递给函数的数…

Linux学习之网络编程3(高并发服务器)

写在前面 Linux网络编程我是看视频学的&#xff0c;Linux网络编程&#xff0c;看完这个视频大概网络编程的基础差不多就掌握了。这个系列是我看这个Linux网络编程视频写的笔记总结。 高并发服务器 问题&#xff1a; 根据上一个笔记&#xff0c;我们可以写出一个简单的服务端…

52. N 皇后 II

这道题我认为关键是建立好行列之间的数组col&#xff0c;表示第i行第col[i]列 i从0到n-1开始遍历&#xff08;已经保证了不同行&#xff09;&#xff0c;在每次遍历中判断每一列&#xff08;相当于判断这一行中&#xff0c;皇后应该放在哪一列&#xff09; 判断函数valid的规…

七、HorizontalPodAutoscaler(HPA)

目录 一、HPA概述&#xff1a; 二、HPA工作机制&#xff1a; 三、HPA流程: 四、HPA API对象: 五、示例&#xff1a; 1、基于CPU的HPA 2、常见问题&#xff1a; 3、基于内存的HPA 一、HPA概述&#xff1a; Horizontal Pod Autoscaler&#xff0c;中文就是水平自动伸缩可…

【洛谷千题详解】P7072 [CSP-J2020] 直播获奖

输入样例&#xff1a; 10 60 200 300 400 500 600 600 0 300 200 100 输出样例&#xff1a; 200 300 400 400 400 500 400 400 300 300 #include<bits/stdc.h> using namespace std; int main() {int n,w,s,a[605]{0};cin>>n>>w;for(int i1;i<n;i){sca…

Java Math类库 | 算法实用总结 | 蓝桥杯java组备赛

Java Math类是Java标准库中的一个数学计算类&#xff0c;可以为我们在算法应用中提供很大的帮助。 且由于Math类中的方法都是静态的&#xff0c;因此可以直接通过类名调用&#xff0c;而不需要创建Math类的实例。使用起来十分便捷&#xff0c;下面列出Math中各函数、常量的使用…

【MySQL】数据处理之增删改

文章目录 一、增加&#xff08;插入&#xff09;INSERT INTO...VALUES(...,...)VALUES的方式添加情况一&#xff1a;为表的所有字段按默认顺序插入数据情况二&#xff1a;为表的指定字段插入数据情况三&#xff1a;同时插入多条记录 将查询结果插入到表中 二、修改&#xff08;…

AcWing 843. n-皇后问题

#include <iostream> #include <cstring> #include <algorithm>using namespace std; const int N 10; int n; int col[N], dg[N N], rdg[N N]; // 列占用// 正对角线占用// 副对角线占用 char table[N][N]; // 棋盘void dfs(int index) {if(i…

彻底理解字符编码

一、前言 为什么要进行编码&#xff0c;这些编码的关系如何&#xff0c;如ASCII&#xff0c;IOS-8859-1&#xff0c;GB2312&#xff0c;GBK&#xff0c;Unicode之间的关系&#xff0c;笔者想要彻底理解字符编码背后的故事&#xff0c;遂进行了探索&#xff0c;具体笔记如下。如…

“绿智中国”亚洲绿色数字生态发展论坛暨中泰基业集团2024产品发布会在渝举行

绿智中国&#xff0c;逐梦未来。2024年1月11日-12日&#xff0c;“绿智中国”亚洲绿色数字生态发展论坛暨中泰基业集团2024产品发布会在重庆盛大举行。以“以数字化引领绿色化&#xff0c;以绿色化带动数字化”为主题&#xff0c;共同见证“绿智中国”崛起的力量。 为积极响应《…

目标检测-One Stage-YOLOv7

文章目录 前言一、YOLOv7的不同版本二、YOLOv7的网络结构二、YOLOv7的创新点三、创新点的详细解读ELAN和E-ELANBoF训练技巧计划型重参化卷积辅助训练模块标签分配Lead head guided label assignerCoarse-to-fine lead head guided label assigner 基于级联模型的复合缩放方法 总…

【MySQL】子查询 综合练习

题目&#xff1a; #1.查询和Zlotkey相同部门的员工姓名和工资#2.查询工资比公司平均工资高的员工的员工号&#xff0c;姓名和工资。#3.选择工资大于所有JOB_ID SA_MAN的员工的工资的员工的last_name, job_id, salary#4.查询和姓名中包含字母u的员工在相同部门的员工的员工号和…

canvas设置圆锥形渐变

查看专栏目录 canvas示例教程100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…