C++特性——inline内联函数

news2024/12/24 9:16:24

1. 内联函数

1.1 C语言的宏

在C语言中,我们学习了用#define定义的宏函数,例如:

#define Add(x, y) ((x) + (y))	//两数相加

相较于函数,我们知道宏替换具有如下比较明显的优点

  • 性能优势: 宏在预处理阶段进行简单的文本替换,没有函数调用的开销,可以节省栈空间
  • 灵活的参数: 宏的参数可以是任意表达式,包括副作用表达式。这使得宏能够以更灵活的方式进行代码替换,可以处理一些复杂的操作。

但是,对应的C语言的宏替换也有这些致命的缺陷:

  • 不进行类型检查: 宏在进行文本替换时不进行类型检查,这可能导致一些潜在的类型错误。
  • 没有作用域: 宏在预处理阶段进行文本替换,没有作用域的概念。如果宏的名称与其他标识符冲突,可能会导致错误或意外行为
  • 不可随意调试: 在调试过程中,很难对宏展开后的代码进行单步调试,因为宏展开发生在预处理阶段,调试器无法直接查看宏的展开结果

注:如果想对C语言的宏有更深的了解,建议看看👉C语言——预处理

1.2 内联函数

而为了解决C语言#define宏所带来的缺陷,C++有了inline关键字

  • 我们在函数的返回值类型前面加入inline关键字,这个函数就成为了内联函数
  • 内联函数会在编译时被展开,从而避免了栈帧开销。
  • 同时,内联函数又具有函数的特性。因此具有类型检查、作用域且方便调试。相较于宏函数更加安全。
  • 可以说内联函数在具有宏函数优点同时也完全解决了宏函数所带来的缺陷

例如:

inline void Func()
{
	printf("Hello World\n");
}

int main()
{

	for (int i = 0; i < 100; i++)
		Func();

	return 0;
}

上面的代码我们声明了一个内联函数Func,在编译过后循环处的调用就会变成:

for (int i = 0; i < 100; i++)
    printf("Hello World\n");	//内联函数Func直接被展开成了函数体内的内容

1.2.1 通过反汇编查看内联函数的展开

VS2019为例:

首先,要用反汇编查看内联函数的展开,首先要对编译器做如下设置:

  1. 首先,将Debug模式改为Release模式

  2. 然后,右击项目名称,点击属性

  3. 接着,配置属性-> C/C++ -> 常规 -> 调试信息格式 ->程序数据库

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 最后,配置属性-> C/C++ -> 优化 -> 内联函数扩展 -> 只适用于_inline

设置完成过后,我们就可以通过返汇编查看内联函数的展开了。

  • 我们先来看看没有加入inline关键字的普通函数:

    在这里插入图片描述

  • 再来看看加入inline关键字的内联函数:

    在这里插入图片描述

1.2.2 内联函数的局限性

既然内联函数可以避免栈帧开销而且安全性也有保证,那是不是可以说以后我们可以将所有的函数都定义成内联函数呢?

当然不可以!!!

首先我们来看一组对比:

在这里插入图片描述

  • 可以发现,不是内联函数的文件空间比是内联函数的文件空间小了16KB
  • 有小伙伴就会问了:不就十几KB嘛,磁盘空间这么大不差这点。但是如果我将一个几百行的函数也写成一个内联函数,那这二者之间占用空间的差距就不会这么小了。

所以我们有必要清楚内联函数的局限,知道什么时候可以用,什么时候不可以用;

  • 通过上面的分析和比较可以知道,inline内联函数实际上是一种空间换时间的做法:通过代码的展开来减少函数调用的开销,但也因此导致了代码膨胀的问题
  • 因此内联函数一般用作代码简短(不超过10行),经常使用的函数
  • 而对于递归函数、存在大量循环的函数、存在switch case语句的函数,一般不用inline处理

1.2.3 内联函数的特性

如果有人不听劝,将一个递归函数定义成内联函数,会出现什么情况呢?

  • 特性1:inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,如果被定义的函数较为复杂,编译器会忽略inline特性
  • 特性2:内联函数的声明和定义最好不要分离,否则就只能在定义内联函数的文件中使用该内联函数

1.3 总结

  • inline内联函数是C++专门针对C语言宏函数的缺陷而设计的。
  • 其既具有宏函数没有函数调用开销,所耗时间少的优点;同时也基本上解决了宏函数不安全、难以调试的缺点。其功能不可谓不强。
  • 然而内联函数也有较大的局限性:其只适用于代码简单、且频繁调用的函数。而对于递归、有大量循环的函数则不适用
  • 内联函数只是对编译器的一个建议,到底才不采用取决于编译器。
  • 内联函数的声明和定义最好放在一起

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

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

相关文章

数据结构-树的概念结构及存储

&#x1f5e1;CSDN主页&#xff1a;d1ff1cult.&#x1f5e1; &#x1f5e1;代码云仓库&#xff1a;d1ff1cult.&#x1f5e1; &#x1f5e1;文章栏目&#xff1a;数据结构专栏&#x1f5e1; 目录 一、树的基本概念及结构 1树的概念 2树的存储 二、二叉树的概念及结构 1二叉树的概…

FPGA的64点FFT代码及报告,verilog快速傅里叶变换

名称&#xff1a;64点FFT快速傅里叶变换Radix4 软件&#xff1a;Quartus 语言&#xff1a;Verilog 代码功能&#xff1a; 使用verilog实现64-point Pipeline FFT处理器 FPGA代码资源下载网&#xff1a;hdlcode.com 代码下载&#xff1a; 名称&#xff1a;64点FFT快速傅里…

保姆级 Keras 实现 Faster R-CNN 十四 (预测)

保姆级 Keras 实现 Faster R-CNN 十四 一. 预测模型二. TargetLayer三. 预测四. 显示预测结果五. 加载训练好的参数六. 效果展示七. 代码下载 上一篇 文章中我们完成了 Faster R-CNN 训练的功能, 现在到了预测部分了 一. 预测模型 因为在预测的时候并不需标签, 所以 RoiLabel…

[Linux打怪升级之路]-system V共享内存

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 本期学习目标&…

基于Ubuntu Server编译YTM32 SDK工程

基于Ubuntu Server编译YTM32 SDK工程 文章目录 基于Ubuntu Server编译YTM32 SDK工程需求下载软件包安装与配置配置虚拟机联网模式启用ssh连接启用ftp连接安装armgcc编译工具链确认make工具 验证 需求 在Linux系统环境下搭建SDK的编译环境&#xff1a; 方便加入到持续集成工具…

16.The Tensor Product:Vector/Covector combinations

本节将概括目前为止所学的张量积知识。并讨论一般张量&#xff0c;它可以由任意数量的向量和协向量的任意组合来生成。 同样&#xff0c;也是使用的非标准的符号。 (2&#xff0c;0)阶张量&#xff0c; 由两个向量生成的。 &#xff08;1&#xff0c;2&#xff09;阶张…

C++学习之多态详解

目录 多态的实现 例题 重载 重写 重定义的区别 抽象类 多态实现原理 多态的实现 C中的多态是指&#xff0c;当类之间存在层次结构&#xff0c;并且类之间是通过继承关联时&#xff0c;就会用到多态。多态意味着调用成员函数时&#xff0c;会根据调用函数的对象的类型来执…

Spring IOC之@ComponentScan

博主介绍&#xff1a;✌全网粉丝4W&#xff0c;全栈开发工程师&#xff0c;从事多年软件开发&#xff0c;在大厂呆过。持有软件中级、六级等证书。可提供微服务项目搭建与毕业项目实战&#xff0c;博主也曾写过优秀论文&#xff0c;查重率极低&#xff0c;在这方面有丰富的经验…

[SWPUCTF 2023 秋季新生赛] web题解

文章目录 colorful_snakeNSS_HTTP_CHEKER一键连接!ez_talkPingpingpingUnS3rialize查查needRCE-PLUSbackup colorful_snake 打开题目&#xff0c;查看js源码 直接搜flag 把那三行代码复制到控制器&#xff0c;得到flag NSS_HTTP_CHEKER 都是http请求基本知识 抓包按照要求来&…

企业知识库管理系统怎么做?

21世纪&#xff0c;一个全新的信息化时代&#xff0c;从最初的传统办公到现在的信息化办公&#xff0c;一个世纪的跨越造就了各种大数据的诞生。 知识库系统 在这个数据横行的时代&#xff0c;文档管理产品市场逐渐兴盛起来&#xff0c;企业知识库管理系统作为企业的智慧信息的…

计算机组成原理new15 磁盘

文章目录 磁盘的结构磁盘的性能指标磁盘阵列固态硬盘SSD关于机械硬盘和固态硬盘的地址 这里计算传输时间和数据传输率是难点 磁盘的结构 注&#xff1a;磁盘的基本读取单位是扇区&#xff0c;但是每次只能读取1bit&#xff0c;这里我们应该理解为磁盘每次的读写操作至少要持续…

初始 c++(1)

目录: 目录 1: 命名空间的详解 2:c的输入与输出关键字及理解 3:详细讲解第一个c程序(每段代码的意思) 4:缺省参数的理解 5:函数重载 引言&#xff1a;从今天开始我们就开始学习c了&#xff0c;让我们一起开始新的知识吧&#xff01; 1&#xff1a;命名空间 所谓的命名空间…

深度学习学习笔记-模型的修改和CRUD

目录 1.打印模型,理解模型结构2.模型保存与加载3.模型的模块CRUD和模块的层的CRUD 1.打印模型,理解模型结构 import torchclass MyModel(torch.nn.Module):def __init__(self):super().__init__()self.layer1 torch.nn.Sequential(torch.nn.Linear(3, 4),torch.nn.Linear(4, …

云计算——网络虚拟化简介

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​ 目录 前期回顾 前言 一.网络虚拟化 二.网络虚拟化介绍 三.为什么要网络虚拟化 四,网络…

STM32+2.9inch微雪墨水屏(电子纸)实现显示

本篇文章从硬件原理以及嵌入式编程等角度完整的介绍了墨水屏驱动过程&#xff0c;本例涉及的墨水屏为2.9inch e-Paper V2,它采用的是“微胶囊电泳显示”技术进行图像显示&#xff0c;其基本原理是悬浮在液体中的带电纳米粒子受到电场作用而产生迁移&#xff0c;从而改变显示屏各…

【C++初阶】小白入门C++

目录 前言&#xff1a;1、C关键字2、命名空间2.1命名空间是什么2.2为什么要有命名空间2.3命名空间怎么使用2.3.1命名空间的写法2.3.2命名空间是可以嵌套的2.3.3使用命名空间的三种方式 3、C输入和输出3.1初识cout和cin3.2C的输入输出可以自动识别变量类型 4、缺省参数4.1缺省参…

Linux:用户和权限

Linux&#xff1a;用户和权限 1. 认知root用户1.1 root用户&#xff08;超级管理员&#xff09;1.2 su和exit命令1.3 sudo命令1.3.1 为普通用户配置sudo认证 2. 用户、用户组管理2.1 用户组管理2.2 用户管理2.3 getent命令 3. 查看权限控制3.1 认知权限信息3.1.1 案例 4. 修改权…

react 实战- 玩转 react 全家桶(进阶)学习

一个命令是怎么运行起来的? Shell运行一个命令,实际上是运行一个脚本 环境变量 装了node以后,node的路径,就被注册到了环境变量里. 一个js的东西,可以注册? bin Webpack配置 构建 import A from A , const Arequire(A) 为什么可以这么写?为哈都行?本质上,是构建工…

人人自媒体的时候,Ai绘画还值得踏入吗?

前言 先说结论&#xff0c;如果你不打算涉足自媒体&#xff0c;平时也从不上网发什么内容去展示自己的话&#xff0c;其实AI绘画对你来说意义不大。但如果你对自媒体感兴趣&#xff0c;会涉及发作品&#xff0c;发内容&#xff0c;甚至去设计图片&#xff0c;那么AI绘画值得你…

【【萌新的SOC学习之自定义IP核的学习与设计】】

萌新的SOC学习之自定义IP核的学习与设计 本章为了更加深入的了解FPGA的自定义IP和IP封装测试等问题 参考了正点原子 第六讲自定义IP核呼吸灯实验 和 第十九章 IP封装与接口定义实验 为了更好的理解自定义IP核 我们先介绍一个带AXI主从接口的IP核 我们可以展开AXI从接口 下…