kotlin知识体系(四) : inline、noinline、crossinline 关键字对应编译后的代码是怎样的 ?

1. inline、noinline、crossinline 的作用

在 Kotlin 里,inlinenoinlinecrossinline 这几个关键字和高阶函数紧密相关,它们能够对高阶函数的行为进行优化和控制。本文接下来会详细介绍它们的作用和原理。

1.1 inline 关键字

inline 关键字用于修饰高阶函数,其作用是在编译时将函数调用处替换为函数体本身,以此避免函数调用的开销,提高代码的执行效率。

1.1.1 示例代码
// 定义一个内联高阶函数
inline fun inlineFunction(block: () -> Unit) {block()
}fun main() {inlineFunction {println("This is an inline function call.")}
}
1.1.2 代码解释

在上述示例中,inlineFunctioninline 关键字修饰。在编译时,inlineFunction 的调用会被替换为函数体内容,这样就不会有额外的函数调用开销。不过,使用 inline 也会使生成的字节码体积增大,因为函数体被复制到了调用处。

1.2 noinline 关键字

当高阶函数被 inline 修饰时,它的所有函数参数默认也会被内联。要是你不希望某个函数参数被内联,就可以使用 noinline 关键字。

1.2.1 示例代码
// 定义一个内联高阶函数,包含一个 noinline 参数
inline fun mixedFunction(inlineBlock: () -> Unit, noinline noInlineBlock: () -> Unit) {inlineBlock()noInlineBlock()
}fun main() {mixedFunction({ println("This is an inline block.") },{ println("This is a non - inline block.") })
}
1.2.2 代码解释

在这个例子中,mixedFunction 是内联函数,inlineBlock 会被内联,而 noInlineBlock 由于使用了 noinline 关键字,不会被内联。noinline 通常用于需要将函数参数存储在变量中或者作为其他函数的返回值的情况。

1.3 crossinline 关键字

在使用 inline 修饰高阶函数时,内联函数参数里不允许有非局部返回(即从外层函数返回)。若需要在 Lambda 表达式中使用 return 语句,但又不想使用 noinline 来避免内联,就可以使用 crossinline 关键字。

1.3.1 示例代码
// 定义一个内联高阶函数,包含一个 crossinline 参数
inline fun crossInlineFunction(crossinline block: () -> Unit) {val wrapper = {block()}wrapper()
}fun main() {crossInlineFunction {// 这里不能使用 return 进行非局部返回,但可以执行其他操作println("Inside crossinline block.")}
}
1.3.2 代码解释

在这个例子中,crossInlineFunction 是内联函数,block 参数使用了 crossinline 关键字。在 block 中不能使用非局部返回,但可以正常执行其他操作。这样既能保证参数被内联,又能在一定程度上控制返回行为。

综上所述,inlinenoinlinecrossinline 关键字在 Kotlin 中用于控制高阶函数及其参数的内联行为,有助于优化代码性能和控制函数返回逻辑。

2.对应编译后的代码是怎样的 ?

下面通过具体示例,详细分析 Kotlin 中 inlinenoinlinecrossinline 关键字在编译后代码的表现。

2.1 inline 关键字

2.1.1 Kotlin 代码示例
inline fun inlineFunction(block: () -> Unit) {println("Before block")block()println("After block")
}fun main() {inlineFunction {println("Inside block")}
}
2.1.2 编译后代码分析

在编译时,inline 函数会被内联展开。上述代码编译后,大致等效于以下 Java 代码(Kotlin 编译成 JVM 字节码,这里用 Java 形式便于理解):

public class Main {public static void main(String[] args) {System.out.println("Before block");System.out.println("Inside block");System.out.println("After block");}
}

inlineFunction 的函数体直接替换了调用处的代码,避免了函数调用的开销。

2.2 noinline 关键字

2.2.1 Kotlin 代码示例
inline fun mixedFunction(inlineBlock: () -> Unit, noinline noInlineBlock: () -> Unit) {inlineBlock()noInlineBlock()
}fun main() {mixedFunction({ println("Inline block") },{ println("Noinline block") })
}
2.2.2 编译后代码分析

inlineBlock 会被内联展开,而 noInlineBlock 不会。编译后的代码大致如下:

public class Main {private static final class NoInlineBlock implements Function0<Unit> {public Unit invoke() {System.out.println("Noinline block");return Unit.INSTANCE;}}public static void main(String[] args) {System.out.println("Inline block");NoInlineBlock noInlineBlock = new NoInlineBlock();noInlineBlock.invoke();}
}

inlineBlock 被内联到调用处,而 noInlineBlock 被封装成一个实现了 Function0 接口的类,通过创建对象并调用 invoke 方法来执行。

2.3 crossinline 关键字

2.3.1 Kotlin 代码示例
inline fun crossInlineFunction(crossinline block: () -> Unit) {val wrapper = {block()}wrapper()
}fun main() {crossInlineFunction {println("Crossinline block")}
}
2.3.2 编译后代码分析

crossinline 保证了 Lambda 表达式不会有非局部返回,但仍然会被内联。编译后的代码大致如下:

public class Main {public static void main(String[] args) {final class Wrapper implements Function0<Unit> {public Unit invoke() {System.out.println("Crossinline block");return Unit.INSTANCE;}}Wrapper wrapper = new Wrapper();wrapper.invoke();}
}

block 被内联到 wrapper 中,同时由于 crossinline 的存在,避免了非局部返回的问题。

总结来说,inline 关键字使函数体在调用处展开,noinline 阻止特定函数参数内联,crossinline 允许内联的同时限制非局部返回,这些关键字在编译后的代码中体现了不同的处理方式。

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

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

相关文章

二叉树之树的高以及遍历

二叉树的高其实很简单就一句话&#xff1a; 从根节点到叶节点的最长路径中的边数就是二叉树的高 int FindHeight(Btree root){int leftheight;int rightheight;if(rootNULL){return -1;}else{leftheightFindHeight(root->left );rightheightFindHeight(root->right );}r…

DeepSeek技术架构解析:MoE混合专家模型

一、前言 2025年初&#xff0c;DeepSeek V3以557万美元的研发成本&#xff08;仅为GPT-4的1/14&#xff09;和开源模型第一的排名&#xff0c;在全球AI领域掀起波澜。其核心创新之一——混合专家模型&#xff08;Mixture of Experts, MoE&#xff09;的优化设计&#xff0c;不…

VMware主机换到高配电脑,高版本系统的问题

原来主机是i3 ,windows7系统&#xff0c;vmware 14.0,虚机系统是ubuntu 14.04。目标新机是i7 14700KF,windows11系统。原以为安装虚拟机&#xff0c;将磁盘文件&#xff0c;虚拟机配置文件拷贝过去可以直接用。 新目标主机先安装了vmware 15&#xff0c;运行原理虚机&#xff0…

数字化转型驱动卫生用品安全革新

当315晚会上晃动的暗访镜头揭露卫生巾生产车间里漂浮的异物、纸尿裤原料仓中霉变的碎屑时&#xff0c;这一触目惊心的场景无情地撕开了“贴身安全”的遮羞布&#xff0c;暴露的不仅是部分企业的道德缺失&#xff0c;更凸显了当前检测与监管体系的漏洞&#xff0c;为整个行业敲响…

VideoHelper 油猴脚本,重塑你的视频观看体验

VideoHelper 油猴脚本&#xff0c;重塑你的视频观看体验 在日常上网看视频时&#xff0c;你是否也被这些问题困扰&#xff1a;视频网站开头的广告又臭又长&#xff0c;找个合适的播放倍速要在一堆选项里翻半天&#xff0c;每次手动调音量、点全屏按钮繁琐又影响沉浸感&#xf…

(C语言)习题练习 sizeof 和 strlen

sizeof 上习题&#xff0c;不知道大家发现与上一张的习题在哪里不一样嘛&#xff1f; int main() {char arr[] "abcdef";printf("%zd\n", sizeof(arr));printf("%zd\n", sizeof(arr 0));printf("%zd\n", sizeof(*arr));printf(&…

Java多线程与高并发专题——使用 Future 有哪些注意点?Future 产生新的线程了吗?

Future 的注意点 1. 当 for 循环批量获取 Future 的结果时容易 block&#xff0c;get 方法调用时应使用 timeout 限制 对于 Future 而言&#xff0c;第一个注意点就是&#xff0c;当 for 循环批量获取 Future 的结果时容易 block&#xff0c;在调用 get方法时&#xff0c;应该…

STM32基础教程——PWM驱动LED呼吸灯

目录 前言 技术实现 原理图 接线图 代码实现 内容要点 PWM基本结构 开启外设时钟 配置GPIO端口 配置时基单元 初始化输出比较单元 输出PWM波形 输出比较通道重映射 前言 PWM(Pulse Width Modulation):一种通过调节脉冲信号的占空比&#xff08;高电平持续时间与整…

算法基础——栈

一、栈的概念 栈是⼀种只允许在⼀端进⾏数据插⼊和删除操作的线性表。 进⾏数据插⼊或删除的⼀端称为栈顶&#xff0c;另⼀端称为栈底。不含元素的栈称为空栈。进栈就是往栈中放⼊元素&#xff0c;出栈就是将元素弹出栈顶。 二、栈的模拟实现 1. 创建 本质还是线性表&#…

JVM类文件结构详解

文章目录 前言代码示例1.魔数2.版本3.常量池4.访问标识与继承信息访问标识继承信息 5.Field 信息6 Method 信息构造方法分析(method-main)main方法分析(method-main) 7.附加属性 前言 在 Java 中&#xff0c;JVM 可以理解的代码就叫做字节码&#xff08;即扩展名为 .class 的文…

5.安全相关(双手启动、安全触边传感器)

一、关于双手启动按钮的使用规范 本文介绍双手启动按钮的使用。概括来讲&#xff1a; 双手按下之间的时间差间隔应该在0.5-2秒之间。一旦释放任何一个按钮&#xff0c;启动信号输出结束。只有两个按钮都被释放之后&#xff0c;才能再次触发双手启动信号。如果某按钮被按下超过…

电脑上不了网普通用户排除方法

1&#xff1a;首先通过电脑的运行/CMD/ipconfig /all 命令查看电脑的ip地址是否正常如图&#xff1a; 2&#xff1a;在命令行中运行&#xff1a;ping 127.0.0.1 如图则正常&#xff0c;否则要重新安装网卡驱动 程序。 3&#xff1a;用ping命令&#xff0c;ping一下同网段的电…

【中文翻译】第3章(1/3)-The Algorithmic Foundations of Differential Privacy

为方便阅读&#xff0c;故将《The Algorithmic Foundations of Differential Privacy》翻译项目内容搬运至此&#xff1b; 教材原文地址&#xff1a;https://www.cis.upenn.edu/~aaroth/Papers/privacybook.pdf 中文翻译版 Github 项目地址1&#xff1a;https://github.com/gu…

2.1词法分析任务

编译器结构 前端 词法分析器的任务 字符流到记号流 eg: 把这些单词就叫做记号 EOF结束符号&#xff01;

Linux操作系统7- 线程同步与互斥5(POSIX条件变量生产者消费者模型的进一步使用)

上篇文章&#xff1a;Linux操作系统7- 线程同步与互斥4&#xff08;基于POSIX条件变量的生产者消费者模型&#xff09;-CSDN博客 本篇代码仓库&#xff1a; 支持处理简单任务的生产者消费者模型代码 生产者-消费者-保存者三线程两队列模型 多生产多消费的生产者消费者模型 进一…

【嵌入式学习2】C语言 - VScode环境搭建

目录 ## 语言分类 ## c语言编译器 ## VScode相关配置 ## 语言分类 编译型语言&#xff1a;C&#xff0c;C解释型语言&#xff1a;python&#xff0c;JS ## c语言编译器 分类GCC 系列MinGWCygwinMSVC系列一套编程语言编译器将GCC编译器和GNU Binutils移植到Win32平台下的产物…

使用Doris broker load导入数据到带Kerberos的HA HDFS的命令详解

以下是关于 Doris Broker Load 结合 Kerberos 认证的 HDFS 数据导入的详细解析&#xff1a; 一、Broker Load 核心原理 Broker Load 是 Doris 中用于从 HDFS/S3 等远程存储系统异步导入大数据的工具&#xff0c;其核心流程如下&#xff1a; 任务提交&#xff1a;用户通过 SQL…

数字化转型 2.0:AI、低代码与智能分析如何重塑企业竞争力?

引言&#xff1a;数字化转型进入2.0时代 在过去的十几年里&#xff0c;企业的数字化转型&#xff08;1.0&#xff09;主要围绕信息化和自动化展开&#xff0c;例如引入ERP、CRM等系统&#xff0c;提高办公效率&#xff0c;减少人为失误。然而&#xff0c;随着市场竞争加剧&…

指针,数组 易混题解析(一)

目录 一.相关知识点 1.数组名是什么&#xff1f; 两个例外&#xff1a; 2.strlen 3.sizeof 4. * ( ) 与 [ ] 的互换 二.一维数组 三.字符数组 1. 字符 &#xff08;1&#xff09;sizeof &#xff08;2&#xff09;strlen 2.字符串 &#xff08;1&#xff09;si…

ABC392题解

A 算法标签: 模拟 #include <iostream> #include <algorithm> #include <cstring>using namespace std;int main() {ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int w[3];for (int i 0; i < 3; i) cin >> w[i];sort(w, w 3);if (w[0]…