【C++】踏上C++学习之旅(四):细说“内联函数“的那些事
文章目录
- 前言
- 1. "内联函数"被创造出来的意义
- 2. 内联函数的概念
- 2.1 内联函数在代码中的体现
- 2.2 普通函数和内联函数的汇编代码
- 3. 内联函数的特性(重点)
- 4. 总结
前言
本章来聊一聊C++的创作者"本贾尼"大佬,为什么要创作出内联函数,以及内联函数的定义和内联函数的实现机制等等。
话不多说,让我们直入主题!💖💖💖
1. "内联函数"被创造出来的意义
请大家先看下面的代码:
#include<stdio.h>
int Add(int x, int y)
{return x+y;
}int main()
{int ret = Add(10, 20);//假设下面有很多地方都要用到Add函数return 0;
}
假设Add函数在主函数中有非常多的地方要使用到,我们的这种写法是最好的吗?
其实,我们这种写法并不好。从函数调用的效率来看,每当我们调用一次函数就要在栈区上开辟一块空间用作函数栈帧,等函数调用完之后,栈帧就会被销毁。但是在栈区上开辟空间以及栈帧的销毁都是会浪费时间资源的,更何况同一个函数调用很多次的情况。
那我们该怎么做呢?有一个办法就是将这个函数以一种绕开编译器在调用函数时会开辟函数栈帧的做法——“宏函数”。
#include<stdio.h>
//宏函数的写法
#define Add(x,y) ((x)+(y))int main()
{int ret = Add(10, 20);//假设下面有很多地方都要用到Add函数return 0;
}
宏函数的工作原理就是,在编译处于预处理阶段时,就会在使用宏函数的地方将对应的代码给替换进去。这样就相当于只是一个代码段了,而不是一个函数。
但是宏函数的写法实在是太容易出错了,而且使用宏函数还有以下的缺点:
- 代码的可读性差
- 不方便调试,复杂
了解了上述场景之后,我们就来了解一下C++的"祖师爷"是如何攻克这个难关的。
C++的"祖师爷"也发现了这个问题,于是他就创造出了一个函数"内联函数",这个函数能够完美的实现上述宏函数的功能和解决和宏函数的缺点。
2. 内联函数的概念
从形式上看:以关键字inline
开头的函数,叫做内联函数。
从功能上看:C++编译器在调用内联函数的地方展开(函数体对应的内容),没有函数调用的消耗,提高效率。
内联函数的写法:
//在函数定义的开头加一个inline关键字
inline int Add(int x, int y)
{return x + y;
}
如果在上述的函数增加了inline关键字,在编译期间编译器会用函数体替换函数的调用。
那我们该怎么查看这个现象呢?可以通过查看汇编代码,来判断!!!
2.1 内联函数在代码中的体现
(VS)查看方式:
- 在release模式下,查看编译器生成的汇编代码中是否存在call Add。(这种方法本人不推荐,因为在release模式下,代码不容易调试)
- 在debug模式下,需要对编译器进行设置,否则不会展开(因为debug模式下,编译器默认不会对代码进行优化)
按我们就得更改一下Debug下的配置信息:
第一步:点击项目文件夹,选择C/C++,之后点击常规,在调试信息格式中选择程序数据库模式。
第二步:继续在C/C++选项卡下,选择优化,在内联函数拓展这块选择只适用于__inline(/0b1)
2.2 普通函数和内联函数的汇编代码
(这里只是举个例子)
普通函数的汇编代码:
内联函数的汇编代码:
对比一下内联函数和普通函数的汇编代码的区别。可以看到的是对于普通函数的调用编译器是根据call指令来执行的。而对于内联函数来说,C++编译器则是直接将函数体里面的内容转换成汇编代码替换到了函数调用的地方。
3. 内联函数的特性(重点)
1.🍉 inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势 :少了调用开销,提高程序运行效率。
2. 🍉inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。
3. 🍉inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。
// 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;
}
// 链接错误:main.obj : error LNK2019: 无法解析的外部符号 "void __cdecl
//f(int)" (?f@@YAXH@Z),该符号在函数 _main 中被引用
4. 总结
本文讲解了内联函数,内联函数是否能够成功实现具体取决于编译器的做法,我们只是给编译器提一个意见。还有一个重要的点是我们定义和声明内联函数时,得两边都用inline,否则,因为inline的作用会使得函数的地址变成代替函数体的代码段的地址,在链接阶段会因为找不到这个函数而报错!
好了,本文就讲到这里了。如果觉得本文好不错的话,麻烦给偶点个赞吧!!!
相关文章:
【C++】踏上C++学习之旅(四):细说“内联函数“的那些事
文章目录 前言1. "内联函数"被创造出来的意义2. 内联函数的概念2.1 内联函数在代码中的体现2.2 普通函数和内联函数的汇编代码 3. 内联函数的特性(重点)4. 总结 前言 本章来聊一聊C的创作者"本贾尼"大佬,为什么要创作出…...
SVN克隆或更新遇到Error: Checksum mismatch for xxx
文章目录 前言问题的产生探索解决方案正式的解决方法背后的故事总结 前言 TortoiseSVN 作为版本控制常用的工具,有一个更为人们熟知的名字 SVN,客观的讲SVN的门槛相比Git而言还是低一些的,用来存储一些文件并保留历史记录比较方便࿰…...
QT交互界面:实现按钮运行脚本程序
一.所需运行的脚本 本篇采用上一篇文章的脚本为运行对象,实现按钮运行脚本 上一篇文章:从0到1:QT项目在Linux下生成可以双击运用的程序(采用脚本)-CSDN博客 二.调用脚本的代码 widget.cpp中添加以下代码 #include &…...
驱动和芯片设计哪个难
驱动和芯片设计哪个难 芯片设计和驱动开发 芯片设计和驱动开发 都是具有挑战性的工作,它们各自有不同的难点和要求。 对于芯片设计,它是一个集高精尖于一体的复杂系统工程,涉及到从需求分析、前端设计、后端设计到流片的全过程。 芯片设计的…...
【云原生】云原生后端:监控与观察性
目录 引言一、监控的概念1.1 指标监控1.2 事件监控1.3 告警管理 二、观察性的定义三、实现监控与观察性的方法3.1 指标收集与监控3.2 日志管理3.3 性能分析 四、监控与观察性的最佳实践4.1 监控工具选择4.2 定期回顾与优化 结论参考资料 引言 在现代云原生架构中,监…...
在 ubuntu20.04 安装 docker
1、替换清华源 替换 sources.list 里面的内容 sudo vim /etc/apt/sources.list# 默认注释了源码镜像以提高 apt update 速度,如有需要可自行取消注释 deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse # deb-src htt…...
前端开发设计模式——观察者模式
目录 一、定义和特点 1. 定义 2. 特点 二、实现方式 1. 使用 JavaScript 实现观察者模式的基本结构 2. 实际应用中的实现示例 三、使用场景 1. 事件处理 2. 数据绑定 3. 异步通信 4. 组件通信 四、优点 1. 解耦和灵活性 2. 实时响应和数据一致性 3. 提高代码的可…...
永磁同步电机高性能控制算法(17)——无差拍预测转速控制
1.前言 前期写了比较多的关于无差拍预测电流控制的东西。 https://zhuanlan.zhihu.com/p/659205719https://zhuanlan.zhihu.com/p/659205719 https://zhuanlan.zhihu.com/p/660266190https://zhuanlan.zhihu.com/p/660266190 https://zhuanlan.zhihu.com/p/719591343https://z…...
【GIT】Visual Studio 中 Git 界面中, 重置 和 还原
在 Visual Studio 的 Git 界面中,“重置” 和 “还原” 是两个常用的 Git 操作。它们的主要区别在于应用场景和影响范围。 1. 重置(Reset) 重置用于更改当前分支的提交历史,通常用于撤销或删除某些提交。重置操作可能会更改 Git…...
开源一款前后端分离的企业级网站内容管理系统,支持站群管理、多平台静态化,多语言、全文检索的源码
大家好,我是一颗甜苞谷,今天分享一款前后端分离的企业级网站内容管理系统,支持站群管理、多平台静态化,多语言、全文检索的源码。 前言 在当今的数字化时代,企业网站和个人博客已成为信息传播和品牌建设的重要渠道。…...
【electron+vue3】使用JustAuth实现第三方登录(前后端完整版)
实现过程 去第三方平台拿到client-id和client-secret,并配置一个能够外网访问回调地址redirect-uri供第三方服务回调搭建后端服务,引入justauth-spring-boot-starter直接在配置文件中定义好第一步的三个参数,并提供获取登录页面的接口和回调…...
Amcor 如何借助 Liquid UI 实现SAP PM可靠性
背景介绍 安姆科是塑料行业的全球领军企业,该企业认识到 SAP 工厂维护(SAP PM)对于确保高效的维护管理的重要性。 在诸如制造业等高度依赖机械设备的行业中,SAP PM是一种通过数据驱动决策来最大限度减少停机时间、降低间接成本、…...
【Redis】常见基本全局命令
一、Redis俩大核心命令 由于Redis是以键值对的形式进行数据存取,自然就离不开不断的存储和获取,而其所对应的命令则是set和get,如此说来二者为Redis的核心基础命令也不为过。 作用:用于存储Stirng类型的数据 返回:当…...
探索国际数据空间(IDS)架构(上)
在当今数字化时代,数据的重要性日益凸显,而国际数据空间(IDS)作为一个新兴的概念,正逐渐成为数据管理和共享的关键领域。今天,我们就来一起探索一下 IDS 的精妙架构。 参考文章:国际数据空间&am…...
如何选择好用的U盘数据恢复软件免费版?2024年热门榜单有哪些?
U盘是我们用来存数据的小玩意儿,又方便又好用。但是,有时候因为不小心删掉了、格式化了或者中病毒了,U盘里的东西就没了,这可让人头疼。好在有很多免费的U盘数据恢复软件能帮我们找回这些丢失的数据。那怎么挑一个好用的免费数据恢…...
音视频入门基础:AAC专题(12)——FFmpeg源码中,解码AudioSpecificConfig的实现
音视频入门基础:AAC专题系列文章: 音视频入门基础:AAC专题(1)——AAC官方文档下载 音视频入门基础:AAC专题(2)——使用FFmpeg命令生成AAC裸流文件 音视频入门基础:AAC…...
UDP组播测试
支持组播的接口: ip a | grep MULTICAST 环回接口虽然显示不支持组播,实际也可以用于本地测试。 添加路由(非必须?): ip route add 239.0.0.0/24 via 10.10.10.206 dev eth0 开放防火墙: 查…...
【Nas】X-Doc:jellyfin“该客户端与媒体不兼容,服务器未发送兼容的媒体格式”问题解决方案
【Nas】X-Doc:jellyfin“该客户端与媒体不兼容,服务器未发送兼容的媒体格式”问题解决方案 当使用Jellyfin播放视频时出现“该客户端与媒体不兼容,服务器未发送兼容的媒体格式”,这是与硬件解码和ffmpeg设置有关系,具体…...
504 Gateway Time-outopenresty
504 Gateway Time-out openresty 问题背景: 当自己点开知乎页面以后,发现官网没有出现任何问题,点击官网以后开始出现各种各样的报错! 一下是来源ai的介绍:(通过搜索这种形式帮助自己进行记忆)…...
SpringBoot篇(自动装配原理)
目录 一、自动装配机制 1. 简介 2. 自动装配主要依靠三个核心的关键技术 3. run()方法加载启动类 4. 注解SpringBootApplication包含了多个注解 4.1 SpringBootConfiguration 4.2 ComponentScan 4.3 EnableAutoConfiguration 5. SpringBootApplication一共做了三件事 …...
《Web性能权威指南》-WebRTC-读书笔记
本文是《Web性能权威指南》第四部分——WebRTC的读书笔记。 第一部分——网络技术概览,请参考网络技术概览; 第二部分——无线网络性能,请参考无线网络性能; 第三部分——HTTP,请参考HTTP; 第四部分——浏览…...
跨境电商独立站:打造你的全球品牌
什么是跨境电商独立站? 跨境电商独立站是指一个独立的电子商务网站,企业可以通过这个网站直接向全球消费者销售产品。与入驻亚马逊、eBay等第三方平台不同,独立站拥有完全自主权,可以自由定制店铺风格、营销策略,并直…...
基于uniapp微信小程序的旅游系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…...
怿星科技薛春宇丨智能汽车软件研发工具链国产化的挑战和探索
2024年7月25日,由上海良益企业管理咨询有限公司主办的“2024域控制器技术论坛“在上海成功举办,十位嘉宾做了精彩分享。“整零有道”将陆续刊出部分演讲的文字实录,以飨读者。 本期刊出怿星科技副总经理薛春宇的演讲实录:智能汽车…...
Flutter动画渐变
User experience is everything. One way to improve it is by making transitions between different UI elements smoother and more visually appealing. This is where the AnimatedCrossFade widget comes in handy. 用户体验就是一切。改善用户体验的方法之一就是让不同…...
Python毕业设计选题:基于Web学生会网站的设计与实现-django
开发语言:Python框架:djangoPython版本:python3.7.7数据库:mysql 5.7数据库工具:Navicat11开发软件:PyCharm 系统展示 系统首页界面 用户注册界面 用户登录界面 校内报道界面 品牌活动界面 个人中心界面 …...
如何选购高性价比百元头戴式耳机?六大选购技巧加性价比耳机推荐
在日益繁忙的生活中,头戴式耳机已成为许多人享受音乐、放松心情的重要工具。然而,市面上的头戴式耳机种类繁多,价格各异,如何选购高性价比百元头戴式耳机?成为了许多消费者的难题。为了帮助大家更好地做出选择…...
Java爬虫的京东“寻宝记”:揭秘商品类目信息
开篇:Java特工的神秘任务 在这个数据驱动的时代,我们就像一群特工,穿梭在数字的海洋中,寻找着隐藏的宝藏——商品类目信息。今天,我们将带领你一起,用Java这把精密的瑞士军刀,深入京东的神秘领…...
React前端框架
React 是一个用于构建用户界面的 JavaScript 库,由 Facebook 开发和维护。React 采用组件化的开发方式,使得开发者可以构建可复用的 UI 组件,从而提高开发效率和代码的可维护性。 React 的基本概念 组件:React 的核心概念是组件…...
React-query vs. 神秘新工具:前端开发的新较量
流畅的分页体验:AlovaJS的分页请求策略 在现代web应用中,分页是一个常见的功能需求。无论是浏览商品列表、查看文章集合,还是管理后台的数据表格,用户都需要一种高效且流畅的方式来浏览大量数据。然而,实现一个流畅且…...
中国水运建设行业协会网站/中国seo排行榜
n_estimators:数值型取值 含义:森林中决策树的个数,默认是10 criterion:字符型取值 含义:采用何种方法度量分裂质量,信息熵或者基尼指数,默认是基尼指数 max_features:取值为int型, float型, string类型…...
个人简介网页怎么做/优化设计单元测试卷
导出聊天记录生成词云看看你和对象聊了什么(可惜我没女朋友) 导出聊天记录打开消息管理器导出的格式选择txt格式(我这里选择导出的路径是桌面所以在桌面上生成了一个包含聊天记录的.txt文件) 干货主要有: ① 200 多…...
长沙城乡建设网站首页/下载班级优化大师并安装
最近一直在准备面试,因为要实习了,然后我就纠结了,不知道自己到底处在一个什么样的水平,到底应该选择怎样的实习单位。但是,不管怎么样,还是多看看题吧,感觉面试题还是挺好玩的。最近又在看《编…...
读书郎营销网站/百度广告联盟赚广告费
字符串操作C语言提供了较多的库函数,本题目要求代码中不能使用字符串操作相关的库函数,可以使用malloc。 用例中可以使用中提供的库函数。 实现接口,每个接口实现1个基本操作: unsigned int strlenth(char*s):计算字…...
什么网站可以做高数/五年级下册数学优化设计答案
基于注解方式的Bean管理 AOP 写法一:匿名内部类 写法二: AOP操作(AspectJ注解) AOP操作(AspectJ配置文件) JdbcTemplate(概念和准备)...
删除wordpress版权信息/免费b2b网站推广
0. 前言本文介绍了使用Kettle对一张业务表数据(500万条数据以上)进行实时(10秒)同步,采用了时间戳增量回滚同步的方法。关于ETL和Kettle的入门知识大家可以阅读相关的blog和文档学习。1. 时间戳增量回滚同步假定在源数据表中有一个字段会记录数据的新增或修改时间&a…...