谈谈inline(内联函数)

news2024/11/20 23:22:52

目录

  • 1、例子抛出
  • 2、 了解inline
    • 2.1 宏替换的副作用
    • 2.2 内联函数
    • 2.3 有意思的点
  • 3、总结
  • 4、 感谢您的阅读!

1、例子抛出

我们知道可以用宏定义来代替一个变量或者函数块:

#define A 20
#define MYFUNC(a,b) ((a) > (b) ?  (a) : (b))

但是用宏定义来替换代码块的时候会有一些副作用(从上面那么多括号也能看出来)。所以想找一种方法来代替宏代码片段,这就是内联函数的作用。

inline int myfunc(int a,int b)
{
	return (a > b ?  a : b)}

2、 了解inline

2.1 宏替换的副作用

几个简单的例子:

// 1 优先级问题
#define MYADD(a,b)  (a) + (b)
 int c = MYADD(a,b) * 3;  // => (a) + (b) * 3  其实是想要(a + b) * 3
// 2 ++,--
#define  MAX(a,b)  ((a) > (b) ? (a) : (b))
  int a = 3,b = 2; 
  int c = MAX(a++,b); // 这块大家可以去试验一下,看看几个变量最后的取值

2.2 内联函数

内联函数是在 C++ 中增加的一个功能,可以提高程序执行效率。如果函数是内联的,编译器在编译时,会把内联函数的实现替换到每个调用内联函数的地方,可以与宏函数作类比,但宏函数不会进行类型检查。
为什么要用内联函数?
先来想想普通函数的调用过程:

# include ...
int add(int a, int b)
{
	return a+b;
}

int main()
{
	int a = 1, b = 2,;
	int c = add(a, b);
	int d = add(c, a);
	int e = add(d, b);
	return 0}

他的调用过程可以这样画出来:
在这里插入图片描述
每执行一次add函数就要压栈跳转返回等一系列操作,如果函数很简单,这样频繁开销也降低了程序的运行效率。

# include ...

// 如果把这个短小精悍的函数变为内联函数
inline int add(int a, int b)
{
	return a+b;
}

int main()
{
	int a = 1, b = 2,;
	// 那么效果就会变成类似这样, 不严谨哈,表达这个意思。
	int c = {
	return a+b;
};
	int d = {
	return c+a;
};
	int e = {
	return d+b;
};

	return 0}

在这里插入图片描述
引入内联函数主要是解决一些频繁调用的小函数消耗大量空间的问题。通常情况下,在调用函数时,程序会将控制权从调用程序处转移到被调用函数处,在这个过程中,传递参数、寄存器操作、返回值等会消耗额外的时间和内存,如果调用的函数代码量很少,也许转移到调用函数的时间比函数执行的时间更长。而如果使用内联函数,内联函数会在调用处将代码展开,从而节省了调用函数的开销。

2.3 有意思的点

内联函数在最终生成的代码中没有定义,c++编译器直接将函数体插入到函数调用的位置

啥意思?你可以告诉自己知道这地方有个内联函数,但是当编译完成时,这块代码块你就可以无视了,因为他已经插入到函数调用的地方去了。所以下面这种写法也可以;

# include ...

int main()
{
	inline int add(int a, int b)
	{
		return a+b;
	}
	
	int a = 1, b = 2,;
	int c = add(a, b);
	int d = add(c, a);
	int e = add(d, b);
	return 0}

但是,一定要注意,内联函数要写在函数调用之前。

3、总结

① 内联函数必须声明和函数体实现写在一块;
② 内联函数在最终生成的代码中没有定义,c++编译器直接将函数体插入到函数调用的位置;
③ 内联函数调用时,没有普通函数调用时的额外开销(压栈出栈等)
④ c++编译器不一定准许函数的内联请求,这时即使写了inline关键字,也不一定编译成内联函数, 短小精悍的才适合定义为内联函数;
⑤ 内联函数由编译器处理,宏替换由预处理器处理(这里会产生一些副作用)
⑥ c++编译器对内联函数有一定限制:

不能存在任何形式的循环语句在内;
不能存在条件太多的判断语句在内;
函数体不能过大;

4、 感谢您的阅读!

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

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

相关文章

Kubernetes双主集群的部署(二)

Kubernetes单主集群的部署(一)_Evens7xxX的博客-CSDN博客 上期完成了单主架构集群的部署,本期将在单主架构的基础上添加Master和负载均衡器 目录 二、k8s双主架构集群的部署 1.另一台Master同样做初始化配置 2.配置 Master02 3.配置负载均…

算法与数据结构31:DC3算法生成后缀数组

算法与数据结构31:DC3算法生成后缀数组什么是后缀数组引出DC3算法DC3算法具体实现DC3算法模板DC3模板的用法一个可以使用DC3的题什么是后缀数组 假设有字符串 aabaabaa 那么从每个位置开始,到结尾位置,截取后缀串,可得 a aa baa …

四面阿里巴巴如愿拿到offer定级P7,为此我筹备了半年

前言 每个程序员都有一个大厂的梦,而互联网大厂首当其冲自然是阿里巴巴最吃香,今天小编就来分享一个小伙进阿里巴巴的面经! “不想进大厂的程序员不是好程序员”哈哈哈 春节过后,本是金三银四之际,大部分人也都准备好…

【RealSense】L515学习记录

Intel RealSense™ SDK 2.0的安装 1、注册服务器的公钥: sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-key F6E65AC044F831AC80A06380C8B3A55A6F3EFCDE || sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-key F6E65AC044F831AC80A06380C8…

ChatGPT:chatGPT本地部署、运行和接口调用

文章目录从 github 下载环境配置conda 创建虚拟环境官方步骤配置环境安装 revChatGPT更改 config.json.example -> config.json将 config.json 移动到 revChatGPT 路径下cookie 信息写入 config.json方式1:使用账号密码作为登录的方法方式2: 使用 ses…

软件测试期末测试题及解析(五套试题共两万余字)

软件测试期末考试复习题题目软件测试期末考试复习题(一)一、单项选择题:二、判断题:三、简答题期末考试复习题(二)一、单项选择题:二、判断题:三、简答题期末考试复习题(…

并查集最重要的优化:路径压缩

本文章将直接讲解优化,对并查集还不理解或忘记的同学可以看以下两篇文章 并查集基础 优化:启发式合并 先赞后看好习惯 今天我们要来说另一种对并查集的优化:路径压缩 也许有些同学看了启发式合并会说:其实优化的也不多啊&…

定时器: Timer (Java)

定时器: Timer一、定时器是什么二、标准库中的定时器三、实现定时器3.1 定时器的构成3.2 实现细节3.3 完整代码一、定时器是什么 定时器也是软件开发中的一个重要组件。类似于一个 “闹钟”,即达到一个设定的时间之后,就执行某个指定好的代码。 定时器…

收藏 | 自然语言处理(NLP)数据集汇总(附下载链接)

🎄🎄【自然语言处理NLP】简介 🎄🎄 自然语言处理(Natural Language Processing, NLP)是计算机科学领域与人工智能领域中的一个重要方向。它研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。自然语言处理是一门…

自制CPU

CPU是计算机的核心部件,其发展历程就是人类文明的发展史。 随着计算机技术的不断发展, CPU也从一开始的功能简单,到现在已经变成功能强大、应用广泛的芯片。 但要想更深入了解 CPU,你需要知道它是如何工作以及为什么这么做的。 你…

数据结构003:有效的数独

原文链接:数据结构003:有效的数独 题目 请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3…

Lecture7:随机梯度下降算法问题及解决、dropout正则化、学习率的选择、迁移学习

目录 1.随机梯度下降算法问题及解决 1.1 随机梯度下降算法SGD的问题 1.2 具有动量的梯度下降算法SGDMomentum 1.3 Nesterov加速梯度法 1.4 AdaGrad 1.5 RMSProp 1.6 融合!Adam算法 2. 学习率的选取 3. 正则化 3.1 dropout正则化 4. 迁移学习 1.随机梯度下…

一篇文章带你了解python数据分析岗位怎么样

前言 嗨喽,大家好呀~这里是爱看美女的茜茜呐 又到了学Python时刻~ 分析目标 各城市对数据分析岗位的需求情况 不同细分领域对数据分析岗的需求情况 数据分析岗位的薪资状况 工作经验与薪水的关系 公司都要求什么掌握什么技能 岗位的学历要求高吗 不同规模的…

详解C语言中的自定义类型(结构体,枚举,联合)

目录 1. 结构体 1.1 结构的声明 1.2 结构的自引用 1.3 结构体变量的定义和初始化 1.4 结构体内存对齐 (计算结构体的大小) 1.5 结构体传参 2. 位段(结构体实现位段) 2.1 什么是位段 2.2 位段的内存分配 2.3 位段的跨平台问题 3. 枚举 …

node.js-http模块学习

目录 1.什么是 http 模块 2.进一步理解 http 模块的作用 3.用node.js创建最基本的 web 服务器 req 请求对象: res 响应对象: 解决中文乱码问题: 根据不同的url响应 不同的html页面 1.什么是 http 模块 http 模块是 Node.js 官方提供的、…

3.Nacos系列之配置管理

上文中我们学习到服务的注册&#xff0c;本文我们进行服务的调用及配置管理相关的实践 1. 服务调用实践 接着上篇文章的代码&#xff0c;我们新建模块nacos-service-consumer 在pom.xml目录下新增依赖 <dependencies><dependency><groupId>org.springfra…

Bean 作用域和生命周期 · Bean 作用域存在的问题 · Bean 六种作用域 · 执行流程 · 生命周期演示

Spring 是用来存储和读取 Bean&#xff0c;因此 Spring 中 Bean 是最核心的操作资源&#xff0c;我们需要深入学习一下 Bean 对象。 一、Bean 的作用域问题1.1 原因分析1.2 作用域定义二、Bean 的六种作用域singleton 单例作用域prototype 原型作用域request 请求作用域session…

【OpenCV学习】第16课:图像边缘提取 - Sobel算子详细剖析(图像梯度)

仅自学做笔记用,后续有错误会更改 理论 卷积的应用 - 图像边缘提取&#xff1a; 边缘是什么&#xff1a;是像素值发生跃迁的地方&#xff0c; 是图像的显著特征之一&#xff0c; 再图像特征提取丶对象检测丶模式识别等方面都有重要作用如何捕捉/提取边缘&#xff1a;对图像求…

关于LuaGC算法的演化概述

2年不用&#xff0c;就忘了&#xff0c;在这记录下。 5.0版本的双色标记清除算法 此算法中&#xff0c;每个对象会有两种标记态&#xff1a;白色和黑色&#xff1b;新创建的对象都是白色 过程&#xff1a; 1.初始化阶段&#xff1a;将root链表中的所有对象放入待检链表中&am…

0204隐函数及由参数方程所确定的函数的导数相关变化率-导数与微分

1 隐函数 定义&#xff1a;设有两个非空数集A,BA,BA,B.对于∀x∈A\forall x\in A∀x∈A&#xff0c;由二元方程F(x,y)0F(x,y)0F(x,y)0对应唯一的y∈By\in By∈B,称此对应关系是二元方程F(X,y)0F(X,y)0F(X,y)0确定的隐函数。 相应的由yf(x)yf(x)yf(x)确定的对应关系称为显函数。…