当前位置: 首页 > news >正文

Rust语言入门教程(七) - 所有权系统

所有权系统是Rust敢于声称自己为一门内存安全语言的底气来源,也是让Rust成为一门与众不同的语言的所在之处。也正是因为这个特别的所有权系统,才使得编译器能够提前暴露代码中的错误,并给出我们必要且精准的错误提示。

所有权系统的三个规则

  • 每个值都有一个所有者,内存中不可能存在一个没有所有者的值;
  • 一个值只有一个所有者, 没有变量可以共享一个值的所有权,其他变量可以借用这个值,但只有一个变量可以拥有它;
  • 如果某个值的所有者超出了它的作用域,这个值也会立刻从内存中被抹去;

所有权的移动

情景A

让我们用示例来说明上面的文字:

let s1 = String::from("abc");
let s2 = s1;
println!("{}", s1); // Error!

上面的例子中, 我们创建了一个字符串变量s1, 然后创建了另一个变量s2, 并将s1的值赋给它。 此时, 在Rust内存中发生的事并不是进行了一次值拷贝, 而是把s1的值移动给了s2, s1不再有值, 因为只有一个变量可以拥有该值。如果我们在进行了上面的操作之后尝试继续使用s1, 就会出现编译器错误:
请添加图片描述
让我们从内存的角度来看看上面的代码发生了什么, 首先创建一个变量s1, 上一章讲解字符串的内容中说到了, String类型的数据结构由指针,长度, 容量三部分组成,这三部分数据被压入栈中。在堆中创建了值abc, s1的指针指向堆中值所在的地址:
请添加图片描述
然后再创建s2, s2的指针, 长度, 容量都会从s1复制,并作为一个新的变量被压入栈中。请添加图片描述
如果到此为止, s1和s2的指针就都指向了同一个内存地址,这样一来,内存安全就不复存在了, 因此Rust会使s1立即失效。请添加图片描述
编译器现在会认为s1是一个已声明但是未被初始化的变量,因此是不能被使用的。如果s1被声明为一个可变的变量,理论上我们还是可以再次对它进行赋值并使用的。但是在上面的代码中,我们没有使用mut关键字声明它为可变,因此s1始终是不可变的,他的值被移动给s2后, s1就只是一个垃圾,不能再被使用了。

如果我们不想移动s1的值,而是真的想要拷贝一份呢,那可以使用clone()函数:

let s1 = String::from("abc");
let s2 = s1.clone();
println!("{}", s1); // Error!

clone()函数在内存中的行为也与值的移动不同, 不仅在栈中会复制一个变量, 在堆中也会复制一份相同的数据,并调整新变量的指针指向新复制的数据地址。
请添加图片描述
在Rust中, copy一般认为是在栈中进行的复制,clone一般认为涉及堆数据及指针更新, 在其他语言中,可以分别对应浅拷贝和深拷贝。

当变量超出作用域时,会被立即销毁,从内存堆栈的角度看,销毁意味着三件事:

  • 析构函数立即执行(如果有的话)
  • 堆中的数据被立即删除
  • 栈中的数据立即弹出

因此,不会存在内存泄漏,悬空指针这样的问题。

情景B

let s1 = String::from("abc");
do_stuff(s1);
println!("{}", s1);  // Error! s1 的值的所有权被移动到了do_stuff的局部变量s中fn do_stuff(s: String) {// do stuff
}

上面的代码中,我们创建了一个String类型的变量s1, 然后创建了一个接受字符串参数但不返回任何内容的函数。如果我们将s1作为参数传递给该函数, s1的值的所有权将被移动到do_stuff函数中的局部变量s 中, 这就意味着s1将失去对其值的所有权,而不能再继续被使用了。那如果我们还想继续使用s1呢,可能会想到这样做:

let mut s1 = String::from("abc");
s1 = do_stuff(s1);
println!("{}", s1);  fn do_stuff(s: String) -> String {s
}

让s1声明为一个可变变量, 让函数返回一个String类型的值,并重新赋值给s1。 看起来是解决了问题,但是总是感觉画蛇添足,怪怪的样子。跳出代码想一想这个问题, 通常,我们将变量传入函数,无非是想要使用这个值, 而其实使用这个值并不一定需要将值的所有权传递给函数,在下一章中,我们会讨论引用与借用,这将解决我们的这种需求。

小结

本章介绍了Rust的所有权系统的规则与示例,接下来会讲解Rust中的引用与借用。

相关文章:

Rust语言入门教程(七) - 所有权系统

所有权系统是Rust敢于声称自己为一门内存安全语言的底气来源,也是让Rust成为一门与众不同的语言的所在之处。也正是因为这个特别的所有权系统,才使得编译器能够提前暴露代码中的错误,并给出我们必要且精准的错误提示。 所有权系统的三个规则…...

【MATLAB源码-第89期】基于matlab的灰狼优化算法(GWO)无人机三维路径规划,输出做短路径图和适应度曲线

操作环境: MATLAB 2022a 1、算法描述 灰狼优化算法(Grey Wolf Optimizer, GWO)是一种模仿灰狼捕食行为的优化算法。灰狼是群居动物,有着严格的社会等级结构。在灰狼群体中,通常有三个等级:首领&#xff…...

线程池的饱和策略有哪些?

线程池的饱和策略是指当线程池中的任务队列已满时,线程池如何处理新提交的任务。常见的饱和策略有以下几种: 阻塞策略 阻塞策略是指当线程池中的任务队列已满时,新提交的任务会等待队列中有空闲位置后再执行。这种策略可以避免过多的任务被…...

Git设置多个仓库同时推送

Git设置多个仓库同时推送 添加 在Git中,有时我们需要将同一份代码推送到不同的远程仓库,只是URL地址不同。 下面是一种优化的方法来设置多个仓库同时推送: # 添加一个新的远程仓库 git remote set-url --add origin2 新的仓库地址这样&am…...

前端入职环境安装

前端入职 后环境安装 ,内函 nodenvmgit微信开发者工具vscode 的安装包 一.node安装-js运行环境 1.node下载,下载地址Node.js 2.配置淘宝镜像 npm config set registry https://registry.npmmirror.com/ 3.查看配置 npm config list 二.nvm安装-切…...

《金融科技行业2023年专利分析白皮书》发布——科技变革金融,专利助力行业发展

金融是国民经济的血脉,是国家核心竞争力的重要组成部分,金融高质量发展成为2023年中央金融工作的重要议题。《中国金融科技调查报告》中指出,我国金融服务业在科技的助力下,从1.0时代的“信息科技金融”、2.0时代的“互联网金融”…...

Introducing the Arm architecture

快速链接: . 👉👉👉 个人博客笔记导读目录(全部) 👈👈👈 付费专栏-付费课程 【购买须知】:【精选】ARMv8/ARMv9架构入门到精通-[目录] 👈👈👈 — 适合小白入门【目录】ARMv8/ARMv9架构高级进阶-[目录]👈👈👈 — 高级进阶、小白勿买【加群】ARM/TEE…...

Python 使用SQLAlchemy数据库模块

SQLAlchemy 是用Python编程语言开发的一个开源项目,它提供了SQL工具包和ORM对象关系映射工具,使用MIT许可证发行,SQLAlchemy 提供高效和高性能的数据库访问,实现了完整的企业级持久模型。 ORM(对象关系映射&#xff0…...

【nlp】4.3 nlp中常用的预训练模型(BERT及其变体)

nlp中常用的预训练模型 1 当下NLP中流行的预训练模型1.1 BERT及其变体1.2 GPT1.3 GPT-2及其变体1.4 Transformer-XL1.5 XLNet及其变体1.6 XLM1.7 RoBERTa及其变体1.8 DistilBERT及其变体1.9 ALBERT1.10 T5及其变体1.11 XLM-RoBERTa及其变体2 预训练模型说明3 预训练模型的分类1…...

IDEA中 java: 警告: 源发行版 11 需要目标发行版 11 如何解决

步骤1找到项目结构,下面有两种方式 步骤2找到 模块中对应的项目,修改对应的源的语言级别和依赖的模块SDK(M) 步骤3,启动一下,看有无问题, 步骤4,去文件-->设置-->构建、执行、部署-->编译器-->…...

APP测试的测试内容有哪些,常见的Bug分类介绍!

对于产品的手机项目(应用软件),主要是进行系统测试。而针对手机应用软件APP的系统测试,我们通常从如下几个角度开展:功能模块测试、兼容性测试、安装和卸载测试、软件更新测试、性能测试、用户体验性测试、交叉事件测试…...

【Java程序员面试专栏 专业技能篇】Java SE核心面试指引(三):核心机制策略

关于Java SE部分的核心知识进行一网打尽,包括四部分:基础知识考察、面向对象思想、核心机制策略、Java新特性,通过一篇文章串联面试重点,并且帮助加强日常基础知识的理解,全局思维导图如下所示 本篇Blog为第三部分:核心机制策略,子节点表示追问或同级提问 异常处理 …...

网络运维与网络安全 学习笔记2023.11.22

网络运维与网络安全 学习笔记 第二十三天 今日目标 VLAN间通信之交换机、VLAN间通信综合案例、浮动路由 VRRP原理与配置、VRRP链路跟踪、VRRP安全认证 VLAN间通信之交换机 单臂路由的缺陷 在内网的VLAN数量增多时,单臂链路容易成为网络瓶颈 三层交换机 具备…...

Android虚拟化

一、开源项目 开源的项目有一些,比如完全虚拟化的: twoyi 两仪由两部分组成:两仪 App,它实际上是一个 UI 渲染引擎,两仪内部运行的 ROM。 但是看telegram和github,这个app没有完整开源,并且最近…...

Nginx如何配置负载均衡

nginx的负载均衡有4种模式: 1)、轮询(默认) 每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器down掉,能自动剔除。 2)、weight 指定轮询几率,weight和访问比率成正比,用于后端服务…...

Python虚拟环境

Python虚拟环境 介绍 虚拟环境(virtual environment),它是一个虚拟化,从电脑独立开辟出来的环境。通俗的来讲,虚拟环境就是借助虚拟机来把一部分内容独立出来,我们把这部分独立出来的东西称作“容器”&am…...

单片机学习4——中断的概念

中断的概念: CPU在处理A事件的时候,发生了B事件,请求CPU迅速去处理。(中断产生) CPU暂时中断当前的工作,转去处理B事件。(中断响应和中断服务) 待CPU将B事件处理完毕后&#xff0…...

Go语言网络爬虫工程经验分享:pholcus库演示抓取头条新闻的实例

网络爬虫是一种自动从互联网上获取数据的程序,它可以用于各种目的,如数据分析、信息检索、竞争情报等。网络爬虫的实现方式有很多,不同的编程语言和框架都有各自的优势和特点。在本文中,我将介绍一种使用Go语言和pholcus库的网络爬…...

Git安装

简单粗暴,跟着步骤一步一步来 右键就会有了...

以太网通讯协议小结--持续更新中

一、以太网介绍 以太网是一种产生较早,使用相当广泛的局域网技术,局域网就是一个区域的网络互联,可以使办公室也可以是学校等等,大小规模不一。 目前以太网根据速度等级分类大概分为:标准以太网(10Mbit/s…...

PicoClaw:10美元硬件上的AI革命,让Mac mini瞬间不香了!

PicoClaw:10美元硬件上的AI革命,让Mac mini瞬间不香了!一只皮皮虾搅动了整个AI助手江湖,95%代码由AI自主生成,在不到10MB内存中跑出完整智能体能力。最近,GitHub上有个项目像火箭般蹿升——PicoClaw&#x…...

智能游戏体验革新:League-Toolkit如何重新定义英雄联盟辅助工具

智能游戏体验革新:League-Toolkit如何重新定义英雄联盟辅助工具 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 在快节奏的英雄联盟…...

HJ166 讨厌鬼进货

题目题解(40)讨论(20)排行 入门 通过率:61.91% 时间限制:1秒 空间限制:256M 知识点贪心 校招时部分企业笔试将禁止编程题跳出页面,为提前适应,练习时请使用在线自测,而非本地IDE。 描述 讨厌鬼需要采…...

RAG系统提示词重构核心要点,深度拆解核心问题架构与应对方案,实战演练

将针对企业级应用优化的Prompt工程方法论迁移至RAG(检索增强生成)系统时,需要进行系统性的范式重构。这并非简单的指令复用,而是涉及从单体模型指令到“检索-生成”双阶段协同的体系升级。 问题解构与核心挑战 企业级RAG系统引入…...

Z-Image Atelier 多模型对比展示:与Stable Diffusion等模型的生成效果PK

Z-Image Atelier 多模型对比展示:与Stable Diffusion等模型的生成效果PK 最近在开源图像生成模型圈子里,Z-Image Atelier 这个名字被讨论得越来越多。很多朋友都在问,这个新冒出来的模型到底怎么样?和我们已经很熟悉的 Stable Di…...

Win10/Win11远程桌面报错‘函数不受支持’?5分钟搞定CredSSP加密Oracle修正

Win10/Win11远程桌面报错‘函数不受支持’?5分钟急救指南 刚准备远程处理工作文件,突然跳出"发生身份验证错误,要求的函数不受支持"的红色警告框——这个场景对需要频繁使用远程桌面的职场人来说简直噩梦。上周我就遇到了同样问题&…...

ROS 2从入门到精通系列(八):参数与配置 - Launch文件进阶实战与架构设计

1. Launch文件在复杂系统中的核心价值 第一次接触ROS 2的Launch文件时,我把它当成了简单的启动脚本。直到参与一个自动驾驶小车项目,需要同时协调5个激光雷达、3个摄像头和多个算法节点时,才真正理解它的威力。Launch文件本质上是一个系统级编…...

SQLMesh社区贡献指南:如何参与开源项目开发

SQLMesh社区贡献指南:如何参与开源项目开发 【免费下载链接】sqlmesh Scalable and efficient data transformation framework - backwards compatible with dbt. 项目地址: https://gitcode.com/gh_mirrors/sq/sqlmesh SQLMesh是一个可扩展且高效的数据转换…...

告别虚拟机!在WSL2的Ubuntu里5分钟搞定LVGL v9.2模拟器(SDL2显示)

在WSL2中5分钟快速搭建LVGL v9.2开发环境 对于习惯Windows开发环境的嵌入式工程师来说,传统虚拟机方案往往显得笨重且资源占用高。WSL2的出现彻底改变了这一局面——它不仅能提供完整的Linux内核支持,还能实现与Windows系统的无缝文件互通和硬件加速。本…...

高性能NoSQL

关系数据库已经非常成熟,强大的 SQL 功能和 ACID 的属性,使得关系数据库广泛应用于各式各样的系统中,但这并不意味着关系数据库是完美的,关系数据库存在如下缺点。 关系数据库存储的是行记录,无法存储数据结构 关系数据…...