首页 > 其他分享 >Rust的Reborrow机制

Rust的Reborrow机制

时间:2024-10-27 12:09:43浏览次数:5  
标签:mut 遍历 min Reborrow let 借用 机制 Rust

最近,在使用Rust时遇到了Reborrow的概念,记录下来以备以后参考。

1. 起因

起因准备对数据进行Min-Max标准化处理,也就是将一系列数据映射到一个新的范围。

首先,需要遍历数据,找出其中的最大值最小值,然后通过公式改变原始数据集的值。

Min-Max公式:标准化后的值 = (原始值 - 最小值) / (最大值 - 最小值)

简化后的代码如下:

fn main() {
    let mut values = vec![10.5, 22.3, 103.5, 45.75];
    let v = &mut values;
    println!("原始数据: {:#?}", v);

    let mut max = f64::MIN;
    let mut min = f64::MAX;

    for n in v {
        if *n > max {
            max = *n;
        }
        if *n < min {
            min = *n;
        }
    }

    println!("max is {}", max);
    println!("min is {}", min);

    println!("开始Min-Max标准化处理...");
    for n in v {
        *n = (*n - min) / (max - min);
    }

    println!("处理后数据: {:#?}", values);
}

运行时有如下错误:

error[E0382]: use of moved value: `v`                                                                     
   --> src/main.rs:22:14
    |
3   |     let v = &mut values;
    |         - move occurs because `v` has type `&mut Vec<f64>`, which does not implement the `Copy` trai
t
...
9   |     for n in v {
    |              - `v` moved due to this implicit call to `.into_iter()`
...
22  |     for n in v {
    |              ^ value used here after move
    |

大概是第9行遍历v的找出最大值和最小值时候,可变借用v的使用权已经转移了,

所以在第22行再次遍历v去修改值的时候,出现错误。

这里,因为Vector没有实现Copy Trait,所以它的可变借用在第一次遍历时,由于隐式的调用了.into_iter(),所有权发生了转移。

如果想多次遍历Vector,可以使用它的不可变借用,比如定义let v = &values;

那么,就可以多次遍历v,因为不可变借用都实现了Copy Trait

但是,我第二次遍历v的时候,还需要修改其中的值,所以必须定义为可变借用let v = &mut values;

通过查询资料,发现Reborrow的机制可以实现上面的需求。

2. Reborrow概念

借用(Borrow)是Rust中的一个重要概念,它是允许代码访问某个值而不获取其所有权的一种机制。

Reborrow则是指在一个已存在的借用基础上创建一个新的借用,

这个新的借用可以是不可变的,也可以是可变的(前提是原始借用是可变的,并且没有其他借用存在)。

总的来说,Reborrow通过在已存在的借用上创建新的借用,从而扩展引用的生命周期并在更广泛的作用域内安全地访问值。

3. 解决方法

下面通过实践来检验对Reborrow概念的理解。

回到第一节中遇到的问题,解决方式就是在第一次遍历v时(第9行),不要把所有权转移出去,

这样,第二次遍历v第22行)的时候,就不会报出"value used here after move"的错误。

根据Reborrow的机制,我们在第9行可以Reborrow可变借用v,这样转移出去的是被再次借用的v,而不是v本身。

改变方法很简单,第9行改为for n in &*v {即可,也就是先还原v(*v),然后Reborrow(&*v)。

修改后再次运行代码:

$  cargo run

原始数据: [
    10.5,
    22.3,
    103.5,
    45.75,
]
max is 103.5
min is 10.5
开始Min-Max标准化处理...
处理后数据: [
    0.0,
    0.12688172043010754,
    1.0,
    0.3790322580645161,
]

values中的数据可以正常转换了。

注意,这里是将vReborrow成一个不可变借用&*v,因为我第一次遍历时不需要改变v

如果想vReborrow成一个可变借用,可以写成:&mut *v

标签:mut,遍历,min,Reborrow,let,借用,机制,Rust
From: https://www.cnblogs.com/wang_yb/p/18508123

相关文章

  • Rust中str又是什么数据类型?
    在Rust中,str是一种字符串切片类型,但它本身是一个动态大小类型,无法直接使用。通常情况下,我们会通过&str或Box<str>等方式来引用str,因为str类型的数据在内存中具有变长特性,编译器无法在编译时确定其具体大小。str的特点和用途动态大小类型(DST)str是一种动态大小类......
  • python垃圾回收机制(十分重要)
    python垃圾回收机制总概​ python采用的是引用计数机制为主,标记-清除和分代收集两种机制为辅的策略,在Python内部记录着所有使用中的对象各有多少引用。​ 在C/C++中采用用户自己管理维护内存的方式。自己管理内存极其自由,可以任意申请内存,但也为大量内存泄露、悬空指针等bug......
  • [rCore学习笔记 031] SV39多级页表的硬件机制
    看到这个题目就知道上一节提到的RISC-V手册的10.6节又有用武之地了.这里只需注意,RV32的分页方案Sv32支持4GiB的虚址空间,RV64支持多种分页方案,但我们只介绍最受欢迎的一种,Sv39。:RISC-V的分页方案以SvX的模式命名,其中X是以位为单位的虚拟地址的长度。虚拟地址和物理地址......
  • 点跟踪论文—CoTracker: It is Better to Track Together使用Transform的时间与空间注
    CoTracker:ItisBettertoTrackTogether使用Transform的时间与空间注意力机制的密集点联合追踪算法详细解析文章概括总结:在之前学习的TrackingEverythingEverywhereAllatOnce(2023ICCV最佳学生论文)与RAFT:RecurrentAll-PairsFieldTransformsforOpticalF......
  • USB协议详解第22讲(USB包-数据包及重传机制)
    USB协议详解第22讲(USB包-数据包及重传机制)1.数据包的分类数据类包有DATA0数据包、DATA1数据包、DATA2数据包、DATAM数据包。2.数据类包的组成我们今天看数据类包的详细结构,数据包的内容由PID域+数据域+16bitCRC域组成,下图为数据包各个域和抓包协议的对应图。3.数据包的功能......
  • java的无锁编程和锁机制
    Java的并发编程中,为了保证线程安全和高性能,采用了两种主要的同步手段:锁机制和无锁编程。以下是对锁机制、无锁编程、死锁及其避免的详细讲解。一、无锁编程无锁编程通过原子操作来避免传统锁,从而减少线程的上下文切换,提升性能。在Java中,通常使用java.util.concurrent.......
  • 直观解释注意力机制,Transformer的核心 | Chapter 6 | Deep Learning | 3Blue1Brown
    目录前言1.前情提要:词嵌入2.注意力是什么?Mole是什么?Tower又是什么?3.注意力模式:“一个毛茸茸的蓝色生物漫步于葱郁的森林”,名词与形容词,查询与键4.掩码:看前不看后5.上下文窗口大小6.值矩阵7.参数有多少8.交叉注意力9.多头注意力10.输出矩阵11.加深网络12.结语......
  • 【Java知识】Java进阶-服务发现机制SPI
    文章目录SPI概述SPI工作原理ServiceLoader代码展示简化的`ServiceLoader`类关键点解释使用示例1.定义服务接口2.实现服务提供者3.配置文件4.加载服务提供者总结SPI使用场景1.数据库驱动2.日志框架3.图像处理4.加密算法5.插件系统6.缓存机制示例代码1.定......
  • 鸿蒙编程江湖:I/O 密集型任务处理及 ArkTS 的异步锁机制
    本文旨在深入探讨华为鸿蒙HarmonyOSNext系统(截止目前API12)的技术细节,基于实际开发实践进行总结。主要作为技术分享与交流载体,难免错漏,欢迎各位同仁提出宝贵意见和问题,以便共同进步。本文为原创内容,任何形式的转载必须注明出处及原作者。I/O密集型任务是指需要进行大量磁盘读......
  • Java SPI 机制详解
    原文:JavaSPI机制详解在面向对象的设计原则中,一般推荐模块之间基于接口编程,通常情况下调用方模块是不会感知到被调用方模块的内部具体实现。一旦代码里面涉及具体实现类,就违反了开闭原则。如果需要替换一种实现,就需要修改代码。为了实现在模块装配的时候不用在程序里面动态指......