RUST的引用和借用

news/2024/10/5 16:42:18/文章来源:https://www.cnblogs.com/nomore007/p/18447842

    上一篇博客说到,移动是转交所有权,而克隆(Copy和Clone)是获得一个和旧值相同的新值的所有权)。

    那么如果我们想不转交所有权又对变量的值进行读取和修改(比如方法的传参问题,会改变所有权,即移动;或者读取和修改的不是原变量的值,即克隆),应该怎么做?

    RUST提供了引用和借用的机制。常规引用是一个指针类型,指向了对象存储的内存地址(和C++的指针比较像);获取变量的引用,则叫做借用。

    引用允许我们获得对值的使用权,但不是所有权。RUST中使用&获得变量的引用。

    C++需要通过*来访问指针指向的值,类似的,RUST也需要使用*来解引用,访问引用指向的值。不过RUST提供了自动解引用功能,大部分时候不需要显式解引用(一些情况如方法传参需要非引用的形参时还是要解引用的)。

struct Point {x: i32,y: i32,
}
fn main() {let p = Point { x: 10, y: 20 };println!("({}, {})", p.x, p.y);   //输出(10, 20)let q=&p;println!("({}, {})", (*q).x, (*q).y);  //输出(10, 20)println!("({}, {})", q.x, q.y);  //输出(10, 20)
}

    刚才说,引用允许获得对变量的使用权。

fn main() {let x = 5;let y=&x;   //y是x的引用println!("y: {}", y);  //输出y: 5println!("x: {}", x);  //输出x: 5
}

    但是上述代码中y只能读取x的值,而不能修改x的值,只实现了我们目标的一半。这又得说到不可变引用和可变引用的概念。

    不可变引用,即只能读取变量的值,不能对值进行修改(相当于C++中的const T*)。上面的例子中y就是一个不可变引用。

    可变引用,即既能读取变量的值,又能对值进行修改。

fn main() {let mut x = 5;let y=&mut x;(*y)+=1;println!("y: {}", y);  //输出y: 6println!("x: {}", x);  //输出x: 6
}

    上述代码中y是x的一个可变引用。使用&mut获取变量的可变引用。需要注意的是,被获取可变引用的变量必须是可变(mut)的。

    看到这里大家可能会想,这和C++的指针有啥区别吗?

    其实还是有的。在RUST中,引用有两条比较重要的限制:

1. 在相同作用域,同一个变量的可变引用只能存在一个。
2. 相同变量的可变引用和不可变引用不能同时存在。

    为什么要有这两条限制呢?原因是可以使Rust在编译期避免数据竞争。而数据竞争会导致未定义行为,这种行为很可能超出我们的预期,难以在运行时追踪,并且难以诊断和修复。
    先看第一条限制。

fn main() {//会报错,y1和y2的作用域重叠了let mut x = 5;let y1=&mut x;let y2=&mut x;println!("y1: {}", y1);//y1的作用域一直到这里结束println!("y2: {}", y2);  //y2的作用域一直到这里结束
}

    再看第二条限制。

fn main() {let mut x = 5;let y1= &x;let y2=&x;let y3=&mut x;  //会报错,因为已经有不可变引用了println!("y1: {}", y1);  //y1作用域到这里结束println!("y2: {}", y2);  //y2作用域到这里结束println!("y3: {}", y3); ////y3作用域到这里结束
}

    再说说引用的作用域。引用的作用域从引用的定义开始,到引用的最后一次使用结束。

fn main() {let mut x = 5;let y1= &x;  //y1的作用域在这里就结束了let y2=&x;   //y2的作用域在这里就结束了let y3=&mut x;  //不会报错
}

    在上述例子中,x的可变引用和不可变引用不会同时存在,所以不会报错。

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

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

相关文章

帝国模板后台上传60几M的文件怎么不行呢

上传大文件时遇到“无法显示该页”的问题,通常是因为 PHP 的配置限制导致的。以下是详细的解决步骤:检查 PHP 配置文件 (php.ini) 打开 php.ini 文件,找到以下配置项并进行修改:upload_max_filesize:单个文件的最大上传大小。 post_max_size:表单提交的最大大小。 memory…

本地环境PHP帝国备份王备份报错mysql_escape_string(): This function is

在使用帝国备份王进行备份和恢复时,如果遇到PHP 5.5环境下的报错,通常是因为一些旧的MySQL函数已经被弃用或移除。具体来说,mysql_escape_string 函数在PHP 5.5中已经被废弃,应该使用 mysql_real_escape_string 替代。 解决方案定位问题文件:找到 function.php 文件的位置…

帝国CMS建立模型字段报错:Row size too large. The maximum row size for the

在帝国CMS中建立模型字段时,如果字段过多或单个字段过长,可能会遇到 MySQL 报错 “Row size too large”。这个错误是因为 MySQL 表的最大行大小限制为 65535 字节(不包括 BLOB 和 TEXT 类型字段)。解决这个问题的方法是将一些字段转换为 TEXT 或 BLOB 类型。 解决方案分析…

帝国CMS登录后台提示您的Cookie没有开启,不能登陆成功的解决方法

当帝国CMS后台登录时提示“您的Cookie没有开启,不能登陆成功”,通常是由于服务器环境中的某些设置导致的。按照以下步骤操作,可以解决这个问题。 操作步骤找到 php.ini 文件:联系你的空间商或登录服务器,找到 php.ini 文件。 通常 php.ini 文件位于服务器的 etc/php/版本号…

帝国CMS GBK编码使用AJAX提交数据中文乱码问题!

在帝国CMS使用GBK编码的环境中,通过AJAX提交数据时可能会遇到中文乱码的问题。这是因为AJAX默认使用UTF-8编码,而帝国CMS使用的是GBK编码。解决这个问题的关键是在接收数据的PHP文件中对数据进行编码转换。 解决方案在接收数据的PHP文件中进行编码转换:使用 iconv 函数将接收…

帝国CMS更新是警告提示warning:imagecreatefromjpeg()的解决方法!

当帝国CMS使用自动缩略图函数时,如果某些图片丢失或损坏,会导致后台更新时出现警告报告。为了解决这一问题,可以采用以下方法: 方法概述备份原有 gd.php 文件。 替换 gd.php 文件。 更新栏目。 恢复原有 gd.php 文件。扫码添加技术【解决问题】专注中小企业网站建设、网站安…

帝国CMS列表页判断是否有标题图片,如果没有就显示指定的图片

在帝国CMS列表页中,如果文章没有标题图片,则可以显示指定的备选图片。这样可以确保页面视觉统一美观,提升用户体验。 方法1:使用PHP判断复制以下代码到列表内容模板:phpif (empty($r[titlepic])) {$pic = ; } else {$pic = <img src=" . $r[titlepic] . " /&…

js问候-早上好、中午好、晚上好

要在帝国CMS中实现头部问候语功能,可以通过以下几个步骤完成:创建 global.js 文件。 在页面中引入 global.js 文件。 调用 hello 函数。步骤详解 1. 创建 global.js 文件新建 global.js 文件:在网站根目录下新建一个名为 global.js 的文件。 将以下代码复制到 global.js 文件…

关于celery的使用

celery是什么?Celery是一个简单、灵活且可靠的,处理大量消息的分布式系统,专注于实时处理的异步任务队列,同时也支持任务调度。 Celery的架构由三部分组成,消息中间件(message broker),任务执行单元(worker)和任务执行结果存储(task result store)组成。 消息中间件…

帝国CMS图片集只能上传10张图片的原因及解决办法_max_file_uploads

在帝国CMS中上传图片时,如果发现上传多张图片但最终只显示部分图片,这通常是由于 PHP 配置中的 max_file_uploads 参数限制导致的。具体来说,这个参数限制了一个表单最多能上传多少个文件。 原因分析 在帝国CMS中,每张图片都会生成一张大图和一张缩略图,因此实际上每次上传…

帝国CMS为什么发布内容时间为“1970-01-01 ”

在发布内容时,如果时间显示为 1970-01-01,通常是因为以下几个原因:字段未设置为录入项:在建立系统模型时,newstime 字段没有被设置为录入项。 字段不可修改:即使设置了录入项,但该字段可能被设置为不可修改。 字段不可增加:该字段可能被设置为不可增加。解决方法 要解决…

网站避免发布内容时出现 1970-01-01 的时间显示问题

系统模型管理页面:在左侧菜单栏中选择“系统模型管理”。 在列表中找到需要编辑的系统模型,点击“编辑”。字段编辑页面:在字段列表中找到 newstime 字段。 在字段设置区域勾选“录入项”、“可修改”、“可增加”选项。 点击“保存”按钮。数据库表结构检查 如果上述设置已…