rust中的reborrow和NLL
reborrow
我们看下面这段代码
fn main() {let mut num = 123;let ref1 = &mut num; // 可变引用add(ref1); // 传递给 add 函数println!("{}", ref1); // 再次使用ref1
}fn add(num: &mut i32) {println!("{}", *num);
}
我们知道可变引用是没有实现Copy trait的,因此,当ref1传递给add函数之后,其所有权应该被转移到add函数内,之后应该无法使用ref1,但是上面这段代码是可以编译,运行的。这是为什么呢?
经过辛苦的寻找,在github上找到了相关的pull request以及rust核心开发者nikomatsakis在这篇文档中提到的reborrow。原文如下:
One of the less obvious but more important coercions is what I call
*reborrowing*, though it's really a special case of autoborrow. The
idea here is that when we see a parameter of type `&'a T` or `&'a mut
T` we always "reborrow" it, effectively converting to `&'b T` or `&'b
mut T`. While both are borrowed pointers, the reborrowed version has
a different (generally shorter) lifetime. Let me give an example where
this becomes important:fn update(x: &mut int) {*x += 1;}fn update_twice(x: &mut int) {update(x);update(x);}In fact, thanks to auto-borrowing, the second function is implicitly
transformed to:fn update_twice(x: &mut int) {update(&mut *x);update(&mut *x);}This is needed because `&mut` pointers are *affine*, meaning that
otherwise the first call to `update(x)` would move the pointer `x`
into the callee, leading to an error during the second call. The
reborrowing however means that we are in fact not moving `x` but
rather a temporary pointer (let's call it `y`). So long as `y` exists,
access to `x` is disabled, so this is very similar to giving `x` away.
However, lifetime inference will find that the lifetime of this
temporary pointer `y` is limited to the first call to `update` itself,
and so after the call access to `x` will be restored. The borrow
checker rules permit reborrowing under the same conditions in which a
move would be allowed, so this transformation never introduces errors.
对应的译文(来自chatgpt3.5的翻译,非常棒)如下:
这段文本描述了Rust中的 "reborrowing" 概念,即重新借用引用的特性,它实际上是 "autoborrow" 的
一种特殊情况。"reborrowing" 的核心思想是,当我们遇到一个类型为 &'a T 或 &'a mut T 的参数时,
我们总是会对它进行 "reborrow",实际上将其转换为 &'b T 或 &'b mut T。虽然这两者都是借用指针,
但 "reborrowed" 版本具有不同(通常更短)的生命周期。
下面通过一个示例来说明 "reborrowing" 为何重要:fn update(x: &mut i32) {*x += 1;
}fn update_twice(x: &mut i32) {update(x);update(x);
}
实际上,由于 "auto-borrowing",第二个函数会被隐式转换为:fn update_twice(x: &mut i32) {update(&mut *x);update(&mut *x);
}
这是因为 &mut 指针是 "affine" 的,这意味着否则第一次调用 update(x) 会将指针 x 移动到被调用的
函数内部,导致第二次调用时发生错误。但是,"reborrowing" 意味着我们实际上并没有移动 x,而是
移动了一个临时指针(我们称之为 y)。只要 y 存在,对 x 的访问就会被禁用,因此这与将 x 移动
出去非常相似。然而,生命周期推断将发现,临时指针 y 的生命周期仅限于第一次调用 update 本身,
因此在调用后访问 x 将会被恢复。借用检查规则允许在允许移动的情况下进行 "reborrowing",
因此此转换永远不会引入错3误。综上所述,"reborrowing" 是 Rust 中的一个重要借用模式,它有助于确保代码的安全性和正确性,
同时允许对数据进行操作而不引入潜在的错误。
这种机制是 Rust 借用系统的一部分,有助于编写安全且高效的代码。
总结一下,对于上面的代码而言:
// 下面这两行是等价的
add(ref1);
add(&mut *ref1);// 对于不可变引用而言也是一样的,但是由于不可变引用实现了Copy trait,通常在不可变引用身上不常见。let num2 = 456;
let ref2 = &num2;// 下面这两行是等价的
my_print(ref2);
my_print(&*ref2);fn my_print(num: &i32) {println!("{}", num);
}
至于为什么大量的文档和资料没有提到reborrow这个问题,可能得归结于此。在pull request中看到了核心开发者认为正式化reborrow时机不对。
NLL
在Rust的早期版本中,生命周期推断基于词法分析(Lexical analysis),而为了解决这个问题,Rust引入了非词法生命周期(Non-Lexical Lifetime),从而提高了编译器对生命周期的理解和推断。
Rust在1.31版本后提供的NLL(Non-Lexical Lifetime)生命周期简化规则。变量的生命周期跟它的作用域等同,而现在,变量的生命周期结束于它最后一次被使用的位置。
fn main() {let mut s = String::from("hello");let r1 = &s;let r2 = &s;println!("{} and {}", r1, r2);// 新编译器中,r1,r2作用域在这里结束let r3 = &mut s;println!("{}", r3);
} // 老编译器中,r1、r2、r3作用域在这里结束// 新编译器中,r3作用域在这里结束
在现在版本的rust编译器上,上面的代码可以通过正确编译,运行。有了NLL,大大增加了在rust中编写代码的灵活性。
相关文章:
rust中的reborrow和NLL
reborrow 我们看下面这段代码 fn main() {let mut num 123;let ref1 &mut num; // 可变引用add(ref1); // 传递给 add 函数println!("{}", ref1); // 再次使用ref1 }fn add(num: &mut i32) {println!("{}", *num); }我们…...
Java设计模式:一、六大设计原则-04:迪米特法则
文章目录 一、定义:迪米特法则二、模拟场景:迪米特法则原则三、违背方案:迪米特法则原则3.1 工程结构3.2 学生、老师、校长类3.2.1 学生类3.2.2 老师类3.2.3 校长类 3.3 单元测试 四、改善代码:迪米特法则原则4.1 工程结构4.2 学生…...
使用docker部署pg数据库
使用 Docker 部署 PostgreSQL 数据库是一种常见的做法,它提供了方便、可移植和可重复的方式来运行数据库。下面是一个简单的示例,用于在 Docker 中部署 PostgreSQL 数据库: 首先,确保您已经安装了 Docker 并正确配置了 Docker 环境…...
Json“牵手”亚马逊商品详情数据方法,亚马逊商品详情API接口,亚马逊API申请指南
亚马逊平台是美国最大的一家网络电子商务公司,亚马逊公司是1995年成立,刚开始只做网上书籍售卖业务,后来扩展到了其他产品。现在已经是全世界商品品种最多的网上零售商和第二互联网公司,亚马逊是北美洲、欧洲等地区的主流购物平台…...
springboot封装查询快递物流
目录 一、ApiClient代码解读二、ApiService代码解读三、HomeController代码解读四、整体代码五、结果展示 一、ApiClient代码解读 这是一个简单的Spring Boot的RestTemplate客户端,用于执行HTTP请求。 首先,这个类被Component注解标记,这意味…...
从C语言到C++_37(特殊类设计和C++类型转换)单例模式
目录 1. 特殊类设计 1.1 不能被拷贝的类 1.2 只能在堆上创建的类 1.3 只能在栈上创建的类 1.4 不能被继承的类 1.5 只能创建一个对象的类(单例模式)(重点) 1.5.1 饿汉模式 1.5.2 懒汉模式 2. 类型转换 2.1 static_cast 2.2 reinterpret_cast 2.3 const_cast 2.4 d…...
go 使用systray 实现托盘和程序退出
1.先 go get 安装 包 go get github.com/getlantern/systray2.使用的代码 func main() {fmt.Println("开始")systray.Run(onReady, onExit) }func onReady() {systray.SetIcon(icon.Data)systray.SetTitle("Awesome App")systray.SetTooltip("Prett…...
Electron之单例+多窗口
Electron之单例多窗口 Electron 24 React 18 单例可以通过app.requestSingleInstanceLock实现,多窗口可以简单通过路由来实现 单例 const gotTheLock app.requestSingleInstanceLock(); if (!gotTheLock) {app.quit(); } else {app.on(second-instance, (event, …...
A Survey of Knowledge-Enhanced Pre-trained Language Models
本文是LLM系列的文章,针对《A Survey of Knowledge-Enhanced Pre-trained Language Models》的翻译。 知识增强的预训练语言模型综述 摘要1 引言2 背景3 KE-PLMs用于NLU4 KE-PLMs用于NLG5 未来的方向5.1 整合来自同质和异质来源的知识5.2 探索多模态知识5.3 提供可…...
动态规划(选择)
链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 作为队伍的核心,forever97很受另外两个队友的尊敬。 Trote_w每天都要请forever97吃外卖,但很不幸的是宇宙中心forever97所在的学校周围只有3家forever97爱吃的外卖。 如果T…...
IIS WebDAV配置,https绑定及asp设置
IIS支持标准CGI,因此可以用程序语言针对STDIN和STDOUT开发。 IIS CGI配置和CGI程序FreeBasic, VB6, VC 简单样例_Mongnewer的博客-CSDN博客 IIS支持脚本解释CGI,因此可以用脚本语言针对STDIN和STDOUT开发。 IIS perl python cbrother php脚本语言配置…...
【计算机视觉项目实战】中文场景识别
✨专栏介绍: 经过几个月的精心筹备,本作者推出全新系列《深入浅出OCR》专栏,对标最全OCR教程,具体章节如导图所示,将分别从OCR技术发展、方向、概念、算法、论文、数据集等各种角度展开详细介绍。 👨&…...
Java 中 Map 初始化的几种方法
# 传统方式 Map<String, String> map new HashMap<>(); map.put("k1", "v1"); map.put("k2", "v2");# java8新特性-双括号初始化 Map<String, String> map1 new HashMap<>() {{put("k1", "v…...
【学习方法论】学习的三种境界、三种习惯、三个要点,三个心态
学习的三种境界、三种习惯、三个要点,三个心态 三种学习境界 苦学 古人云:“头悬梁、锥刺股”,勤学苦练是第一境界。处于这种层次的同学,觉得学习枯燥无味,对他们来说学习是一种被迫行为,体会不到学习中的…...
[管理与领导-67]:IT基层管理者 - 辅助技能 - 4- 职业发展规划 - 评估你与公司的八字是否相合
目录 前言: 一、概述 二、八字相合的步骤 2.1 企业文化是否相合 2.2.1 企业文化对职业选择的意义 2.2.2 个人与企业三观不合的结果 2.2.3 什么样的企业文化的公司不能加入 2.2 公司的发展前景 2.3 公司所处行业发展 2.4 创始人的三观 2.5 创始人与上司的…...
【PMO项目管理】深入了解项目管理 | Stakeholder 利益相关者 | 利益相关者之间的立场差异
💭 写在前面:本文将带您深入了解项目管理的核心概念和关键要素。我们将从项目管理的基本理解开始,逐步探讨其领域、复杂性和变化的重点,以及项目管理的具体过程。我们还将研究项目的性质以及成功项目所必备的条件。在此过程中&…...
设计模式-原则篇-01.开闭原则
简介 可以把设计模式理解为一套比较成熟并且成体系的建筑图纸,经过多次编码检验目前看来使用效果还不错的软件设计方案。适用的场景也比较广泛,在使用具体的设计模式之前先要学习软件设计的基础 “软件设计原则”,后面的23个设计模式都是…...
JAVA毕业设计096—基于Java+Springboot+Vue的在线教育系统(源码+数据库+18000字论文)
基于JavaSpringbootVue的在线教育系统(源码数据库18000字论文)096 一、系统介绍 本系统前后端分离 本系统分为管理员、用户两种角色(管理员角色权限可自行分配) 用户功能: 注册、登录、课程预告、在线课程观看、学习资料下载、学习文章预览、个人信息管理、消息…...
windows环境搭建ELK
目录 资源下载(8.9.1) ES安装、注册、使用 Kibana安装、注册、使用 Logstash安装、注册、使用 Filebeat安装、使用(如果只有一个数据流,则不需要使用filebeat,直接上logstash即可) 资源下载࿰…...
langchain介绍之-Prompt
LangChain 是一个基于语言模型开发应用程序的框架。它使得应用程序具备以下特点:1.数据感知:将语言模型与其他数据源连接起来。2.代理性:允许语言模型与其环境进行交互 LangChain 的主要价值在于:组件:用于处理语言模型…...
TranslucentTB:3分钟打造Windows任务栏透明效果的终极指南
TranslucentTB:3分钟打造Windows任务栏透明效果的终极指南 【免费下载链接】TranslucentTB A lightweight utility that makes the Windows taskbar translucent/transparent. 项目地址: https://gitcode.com/gh_mirrors/tr/TranslucentTB 想让你的Windows桌…...
如何用Python自动化脚本轻松抢到大麦网演唱会门票
如何用Python自动化脚本轻松抢到大麦网演唱会门票 【免费下载链接】DamaiHelper 大麦网演唱会演出抢票脚本。 项目地址: https://gitcode.com/gh_mirrors/dama/DamaiHelper 还在为抢不到心仪演唱会门票而烦恼吗?面对秒光的票源和昂贵的黄牛票,手动…...
MoviePilot连接TMDB异常的终极诊断指南:5步快速排查与完整解决方案
MoviePilot连接TMDB异常的终极诊断指南:5步快速排查与完整解决方案 【免费下载链接】MoviePilot NAS媒体库自动化管理工具 项目地址: https://gitcode.com/gh_mirrors/mo/MoviePilot MoviePilot作为NAS媒体库自动化管理工具,其核心功能依赖TheMov…...
AI智能体技能库开发实战:从工具调用到系统集成
1. 项目概述:一个智能体技能库的诞生如果你正在研究或开发AI智能体,尤其是基于大型语言模型(LLM)的自主智能体,那么你一定遇到过这样的困境:智能体的核心能力,除了模型本身的理解和生成…...
告别手动抢红包!用Kotlin写一个Android微信红包监听助手(附完整代码)
用Kotlin构建Android微信红包自动化工具:从原理到避坑指南 春节聚会时,你是否曾因低头抢红包错过亲友的精彩对话?工作群里的手气红包总在分神时一闪而过?作为一名Android开发者,其实可以用技术优雅解决这些烦恼。本文…...
CircuitPython开发板选型指南:从需求到Adafruit产品实战解析
1. 项目概述:为什么选择CircuitPython开发板是个技术活如果你刚开始接触硬件编程,或者是从Arduino转向更友好的开发环境,那么CircuitPython绝对是一个让人眼前一亮的选项。它把Python的简洁语法带到了微控制器上,让你能用几行代码…...
BERT PyTorch实现避坑指南:torch.gather()、GELU激活函数与数据预处理那些事儿
BERT PyTorch实现避坑指南:torch.gather()、GELU激活函数与数据预处理那些事儿 当你第一次尝试在PyTorch中实现BERT模型时,可能会遇到一些令人困惑的技术细节。本文将从实际调试的角度,深入解析三个最容易卡住开发者的关键点:torc…...
眉山奶油风家具的实际使用效果如何?奶油风家具
测评主体公示本次测评将对以下品牌进行对比:唯品名居家居、顾家家居、芝华仕、左右沙发、全友家居。所有品牌的测评将遵循统一标准,包括测评维度、动作、环境和数据采集方法。测评维度与标准1. 材质质量动作:检查家具表面材质、内部结构 过程…...
基于sagents框架的AI智能体开发:从核心原理到实战应用
1. 项目概述:一个面向开发者的AI智能体构建框架最近在AI应用开发圈子里,一个名为sagents的开源项目开始引起不少同行的注意。如果你正在寻找一个能帮你快速构建、测试和部署AI智能体(Agent)的框架,而不是从零开始造轮子…...
Claude任务大师浏览器扩展:AI自动化工作流与Chrome插件开发实战
1. 项目概述与核心价值最近在折腾AI自动化工作流,发现一个痛点:虽然像Claude这样的AI助手能力很强,但每次想让它帮我处理网页内容,都得手动复制粘贴,效率实在太低。直到我发现了GitHub上一个名为“claude-task-master-…...
