Rust 所有权 借用与引用
文章目录
- 发现宝藏
- 1. 所有权(Ownership)
- 2. 引用(References)
- 2.1 不可变引用
- 2.2 可变引用
- 2.3 引用的规则
- 3. 悬垂引用(Dangling References)
- 4. 借用(Borrowing)
- 结论
发现宝藏
前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【宝藏入口】。
Rust的所有权系统是其安全性和性能的核心,它通过一套严格的规则来管理内存使用,防止数据竞争和悬垂引用。理解这些规则对于编写高效且安全的Rust代码至关重要。本文将详细探讨Rust中的引用、借用及其规则,并讨论如何利用这些特性来编写健壮的代码。
1. 所有权(Ownership)
在Rust中,所有权是内存管理的基础。每个值在Rust中都有一个所有者,当所有者离开作用域时,值会被自动释放。这种机制消除了手动内存管理的需要,并避免了内存泄漏和悬垂引用等问题。
fn main() {let s1 = String::from("hello");let s2 = s1; // s1 的所有权被转移到 s2// println!("{}", s1); // 这行会导致编译错误,因为 s1 不再拥有 "hello"
}
在这个例子中,s1的所有权被转移给了s2,s1不再有效。
2. 引用(References)
引用是Rust中实现借用(borrowing)的一种方式。它允许你在不获取所有权的情况下使用值。这对于避免不必要的内存拷贝非常有用。Rust中有两种类型的引用:
- 不可变引用(Immutable Reference):允许你读取值但不允许修改它。
- 可变引用(Mutable Reference):允许你修改值,但在同一时间只能有一个可变引用。
2.1 不可变引用
不可变引用使用&符号创建:
fn main() {let s1 = String::from("hello");let len = calculate_length(&s1);println!("The length of '{}' is {}.", s1, len);
}fn calculate_length(s: &String) -> usize {s.len()
}
在这个例子中,calculate_length函数接收一个不可变引用&String,允许函数读取字符串的长度,但不允许修改它。原始字符串s1在函数调用后仍然有效。
2.2 可变引用
可变引用使用&mut符号创建,并且只能在特定条件下使用:
fn main() {let mut s = String::from("hello");change(&mut s);println!("{}", s);
}fn change(some_string: &mut String) {some_string.push_str(", world");
}
在这个例子中,我们创建了一个可变引用&mut s并传递给change函数,允许该函数修改字符串的内容。为了确保数据一致性,Rust要求在同一时间只能有一个可变引用。
2.3 引用的规则
- 同一时间只能有一个可变引用:在某个作用域内,只有一个可变引用可以存在,防止数据竞争。
- 多个不可变引用是允许的:同一时间可以有多个不可变引用,但不可变引用不能与可变引用共存。
- 引用必须有效:引用的生命周期不能超过其指向的数据的生命周期。
3. 悬垂引用(Dangling References)
悬垂引用是指指向已经释放内存的引用。Rust通过其所有权系统防止悬垂引用的产生。编译器确保所有引用在其数据被释放之前不会超出作用域。
fn dangle() -> &String { // 错误:返回引用时,引用的数据已被释放let s = String::from("hello");&s
}
在这个例子中,dangle函数试图返回一个指向局部变量s的引用,但s在函数返回后会被释放。Rust编译器会阻止这种情况的发生,并报告编译错误。
4. 借用(Borrowing)
借用是Rust中的一个重要概念,它允许函数在不获取所有权的情况下使用值。借用有两种形式:不可变借用和可变借用。
- 不可变借用:允许多个不可变借用同时存在。它们可以读取数据,但不能修改。
- 可变借用:允许一个可变借用存在,它可以修改数据,但在此期间不允许任何不可变借用或其他可变借用存在。
fn main() {let mut s = String::from("hello");let r1 = &s; // 不可变借用let r2 = &s; // 另一个不可变借用// let r3 = &mut s; // 错误:同时存在不可变借用时不能有可变借用println!("{} and {}", r1, r2);let r3 = &mut s; // 不可变借用的作用域已结束r3.push_str(", world");println!("{}", r3);
}
在这个例子中,我们首先创建了两个不可变借用r1和r2,然后在它们的作用域结束后创建了一个可变借用r3。
结论
Rust的所有权、引用和借用机制提供了一种强大而安全的内存管理方式。通过这些机制,Rust能够在编译时避免许多常见的内存错误,如悬垂引用和数据竞争。尽管这些规则可能在开始时显得复杂,但它们为你提供了一个强大的工具集来编写安全、并发的代码。掌握这些概念后,将能够充分利用Rust的强大特性来构建高效的程序。
相关文章:
Rust 所有权 借用与引用
文章目录 发现宝藏1. 所有权(Ownership)2. 引用(References)2.1 不可变引用2.2 可变引用2.3 引用的规则 3. 悬垂引用(Dangling References)4. 借用(Borrowing)结论 发现宝藏 前些天…...
构建智能电商新生态:深度解析京东商品详情API的力量
在当今数字化浪潮中,智能电商系统已成为推动零售业转型升级的重要引擎。作为电商行业的领军者之一,京东凭借其庞大的商品数据库和先进的技术架构,为开发者与商家提供了丰富的API接口,其中商品详情API无疑是构建智能电商系统的关键…...
Golang | Leetcode Golang题解之第398题随机数索引
题目: 题解: type Solution []intfunc Constructor(nums []int) Solution {return nums }func (nums Solution) Pick(target int) (ans int) {cnt : 0for i, num : range nums {if num target {cnt // 第 cnt 次遇到 targetif rand.Intn(cnt) 0 {ans …...
使用注意力机制可以让你的模型更加灵活,但是需要额外的计算资源。rnn lstm bilstm attension
确实,使用注意力机制可以使模型更加灵活,但也确实需要额外的计算资源。注意力机制允许模型在处理序列数据时,能够动态地关注不同位置的重要性,从而更好地捕捉长依赖关系。下面是一个简单的注意力机制实现示例,可以帮助…...
git命令大全
简介:个人学习分享,如有错误,欢迎批评指正 一、Git操作流程 1、代码提交和同步代码 第零步: 工作区与仓库保持一致第一步: 文件增删改,变为已修改状态第二步: git add ,变为已暂存状态 $ git status $ git add --al…...
【数据仓库】数据仓库常见的数据模型——范式模型
目录 一、范式 1、第一范式 2、第二范式 3、第三范式 4、进一步范式化:BCNF、4NF 和 5NF 简介 (1)Boyce-Codd 范式(BCNF) (2)第四范式(4NF) (5&#x…...
【LeetCode每日一题】——LCR 078.合并 K 个升序链表
文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目注意】六【题目示例】七【题目提示】八【解题思路】九【时间频度】十【代码实现】十一【提交结果】 一【题目类别】 优先队列 二【题目难度】 困难 三【题目编号】 LCR 078.合并 K 个升序链表 …...
代码随想录算法训练营第五十九天 | dijkstra(堆优化版)精讲
目录 dijkstra(堆优化版)精讲 思路 堆优化细节 方法一: 最小堆优化 dijkstra(堆优化版)精讲 题目链接:卡码网:47. 参加科学大会 文章讲解:代码随想录 小明是一位科学家&#x…...
go语言后端开发学习(七)——如何在gin框架中集成限流中间件
一.什么是限流 限流又称为流量控制(流控),通常是指限制到达系统的并发请求数。 我们生活中也会经常遇到限流的场景,比如:某景区限制每日进入景区的游客数量为8万人;沙河地铁站早高峰通过站外排队逐一放行的…...
SpringBoot2:web开发常用功能实现及原理解析-整合EasyExcel实现Excel导入导出功能
1、工程包结构 主要是这5个Java类 2、导入EasyExcel包 这里同时贴出其他相关springboot的基础包 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><depend…...
CTFShow-信息搜集
Web1: 题目描述:开发注释未及时删除 。 打开题目后提示web1:where is flag? ctrlu读取源码。 Web2: 题目描述:js前台拦截 无效操作 打开题目后显示:无法查看源代码 右键无法用,…...
Facebook的虚拟现实功能简介:社交网络的新前沿
在科技飞速发展的今天,虚拟现实(VR)已经从科幻小说中的梦想变成了触手可及的现实。作为全球领先的社交平台,Facebook(现已更名为Meta)正大力推动虚拟现实技术的发展,以重新定义用户的社交体验。…...
Redis embstr 编码
embstr 编码 是 Redis 中一种优化存储小型字符串的编码方式。它是 Redis 内部存储字符串的多种方式之一,特别适用于存储长度不超过 44 字节的小字符串。...
【Elasticsearch系列二】安装 Kibana
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
中国电子学会202403青少年软件编程(Python)等级考试试卷(三级)真题与解析
202403Python 三级真题 一、选择题 1.在 Python 中,hex(2023)的功能是?( ) A.将十进制数 2023 转化为十六进制数 B.将十进制数 2023 转化为八进制数 C.将十六进制数 2023 转化为十进制数 D.将八进制数 2023 转化为十进制数 2.下列表达式的值与其他三个选项不相…...
k8s 资源管理
文章目录 ResourceQuota什么是资源配额定义一个ResourceQuotaResourceQuota的使用 LimitRangeLimitRange的用途示例1:配置默认的requests和limits示例2:配置requests和limits的范围 QoS什么是服务质量保证示例1:实现QoS为Guaranteed的Pod示例…...
演示:基于WPF的自绘的中国地铁轨道控件
一、目的:演示一个基于WPF的自绘的中国地铁轨道控件 二、效果演示 北京地铁 成都地铁 上海地铁 深圳地铁 南京地铁 长春地铁 哈尔滨地铁 武汉地铁 厦门地铁 香港地铁 三、功能 支持平移、缩放等操作 鼠标悬停显示线路信息和站点信息 按表格显示,按纸张…...
设计模式(Design Patterns)
设计模式(Design Patterns)是软件开发人员在软件设计过程中面临的一般性问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。设计模式的目的是为了提高代码的可重用性、可维护性、可读性、可靠性以及灵活性。设…...
C++:opencv生成结构元素用于膨胀腐蚀等cv::getStructuringElement
cv::getStructuringElement 是 OpenCV 库中用于生成结构元素的函数。结构元素在形态学操作中(如膨胀、腐蚀、开运算、闭运算等)扮演着关键角色。这个函数可以创建不同形状和尺寸的结构元素,以适应不同的图像处理需求。 函数原型 cv::Mat cv…...
最大余额法,解决百分比计算相加不等于100%(扇形/饼图百分比使用的此算法)
在开发项目的过程中有时候需要进行计算百分比,例如计算饼状图百分比。有时候在计算的过程中常规四舍五入计算会发生所有计算的值相加不等于100%的情况 这是 get_percent_value 函数的 JavaScript 版本: /*** 最大余额法,解决百分比计算相加不…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
