当前位置: 首页 > 知识库问答 >
问题:

rust - Rust中借用和隐式重借用的区别?

朱兴学
2023-10-04

rust新手,看到隐式重借用,有些不解,望能够帮忙解答。

下面代码都是重复可变引用,但为什么通过隐式重借用方式,就可以实现多个可变引用?rust不是明确说同一时间只能有一个可变引用吗?

// err 能够理解,rust明确不能有两个可变引用。fn compile_err() {    let mut s = String::from("hello");    let r1 = &mut s;    {        let r2 = &mut s;        dbg!(r2);    }    dbg!(r1);  // compile ERR}// 但通过隐式重借用,为啥就可以,(*r1) 解应用的最终对应的不还是 s?fn compile_ok() {    let mut s = String::from("hello");    let r1 = &mut s;    {        let r2 = &mut (*r1);        dbg!(r2);    }    dbg!(r1);  // compile OK}

共有1个答案

宗政唯
2023-10-04

borrow-checker 是一个编译期的检查。在实际的程序中,在编译期看到 *r1 的时候,通常是很难确定其实际对象是什么的。(虽然在你的这个简单的程序中可以比较容易确定,但是这种情况在实际的程序中会是比较少见的。)所以 borrow-check 不会把 *r1s 当成同一个对象进行检查。

同时,在 r2 存在时,r1 已经不能使用了。因为使用 r1, 通常就意味着要对 *r1 进行 borrow 。borrow-checker 会在 r2 存在时阻止再次对 *r1 进行 borrow。
比如:

        let mut s = String::from("s");        let r1 = &mut s;        {            let r2 = &mut (*r1);            let l = r1.len(); // ERROR            r2.push('2');            r1.push('3'); // ERROR            println!("{}", r2);        }        println!("{}", r1);

因为,此处的两个对 r1 的使用,分别需要对 *r1 进行 borrow / mutable borrow 。而 r2 的存在使得对 *r1 进行此类操作不可能。

所以,同时还是只有一个“可用的”对 s 的 mutable borrow。

    let r1 = &mut s;    {        let r2 = &mut s;        dbg!(r2);    }    dbg!(r1);

不会有这个效果。如果 let r1 = &mut s 合法,那么 r1r2 将是同时可用的。

 类似资料:
  • 在通过 let 绑定来进行模式匹配或解构时,ref 关键字可用来接受结构体/元组的字段的引用。下面的例子展示了几个实例,可看到 ref 的作用: #[derive(Clone, Copy)] struct Point { x: i32, y: i32 } fn main() { let c = 'Q'; // 赋值语句中左边的 `ref` 关键字等价右边的 `&` 符号。

  • 我正在编写一个Rust程序来收集每个输入行的第一个字,这有点类似于Unix实用程序。 这让我 我读过《不能作为可变借来》一书,因为它也是作为不可变借来的,但我仍然感到困惑:可变借来发生在第10行,而不可变借来发生在第12行,那么“已经作为不可变借来的变量是作为可变借来的”怎么可能发生呢?至少错误应该是“一个已经作为可变(在第10行)借用的变量被作为不可变(在第12行)借用”。

  • 这篇教程是现行 3 个 Rust 所有权系统章节的第二部分。所有权系统是 Rust 最独特且最引人入胜的特性之一,也是作为 Rust 开发者应该熟悉的。Rust 所追求最大的目标 -- 内存安全,关键在于所有权。所有权系统有一些不同的概念,每个概念独自成章: 所有权,关键章节 借用,你正在阅读的这个章节 生命周期,关于借用的高级概念 这 3 章依次互相关联,你需要完整地阅读全部 3 章来对 Rus

  • 首先,我试过这样的方法: 它不能被编译,因为 不能将“vec”作为不可变项借用,因为它也是作为可变项借用的 我认为Rust借用检查器可以比这更聪明,所以我找到了一个叫做NLL的东西,它应该可以解决这个问题。 我试过样本: 它可以工作,但为什么它现在使用的是?他们俩都吃了一顿饭

  • 首先,我尝试了这样的方法: 它不能被编译,因为 我想这个样本可以解决这个问题 它可以工作,但是为什么它现在与一起工作?

  • 当数据被不可变地借用时,它还会冻结(freeze)。已冻结(frozen)数据无法通过原始对象来修改,直到指向这些数据的所有引用离开作用域为止。 fn main() { let mut _mutable_integer = 7i32; { // 借用 `_mutable_integer` let _large_integer = &_mutable_