< 返回版块

Aphrodit 发表于 2021-02-07 02:15

Tags:引用

为啥这样不能编译

fn main() {
    let mut x = 5;
    let y = &mut x;
    println!("{}", x);
    println!("{}", y);
}

而调换println顺序后就可以编译了

fn main() {
    let mut x = 5;
    let y = &mut x;
    println!("{}", y);
    println!("{}", x);
}

评论区

写评论
eweca 2021-02-10 18:19

话说编译器不是有提醒么:

error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
 --> src\main.rs:4:20
  |
3 |     let y = &mut x;
  |             ------ mutable borrow occurs here
4 |     println!("{}", x);
  |                    ^ immutable borrow occurs here
5 |     println!("{}", y);
  |                    - mutable borrow later used here

error: aborting due to previous error

println!要求借走一个不可变借用,但你之后又使用了不可变借用,有冲突。第二个例子里,可变借用最后使用的地方在不可变借用之前,自动drop掉可变借用。所以现在可以借到不可变借用。

Bai-Jinlin 2021-02-09 19:43

我感觉你的两个代码可以这么理解,下面的代码有无效的语法,仅供演示。

'a: {
    let mut x:i32 = 5;
    'b: {
        let y:&'b i32 = &'b mut x;
        println!("{}", x);
        println!("{}", y);
    }
}
'a: {
    let mut x:i32 = 5;
    'b: {
        let y:&'b i32 = &'b mut x;
        println!("{}", y);
    }
    println!("{}", x);
}
xinlingjushi 2021-02-09 16:12

可变借用的问题 引用下面的话: 通过引用,你可以拥有你想拥有的任意多的引用,因为它们没有一个在写。如果你在写,并且你需要2个或更多相同内存的指针,则你只能一次拥有一个&mut。这就是Rust如何在编译时避免数据竞争:如果打破规则的话,我们会得到错误。

生命周期 借出一个其它人所有资源的引用可以是很复杂的。例如,想象一下下列操作:

我获取了一个某种资源的句柄 我借给你了一个关于这个资源的引用 我决定不再需要这个资源了,然后释放了它,这时你仍然持有它的引用 你决定使用这个资源 噢!你的引用指向一个无效的资源。这叫做悬垂指针(dangling pointer)或者“释放后使用”,如果这个资源是内存的话。

要修正这个问题的话,我们必须确保第四步永远也不在第三步之后发生。Rust 所有权系统通过一个叫生命周期(lifetime)的概念来做到这一点,它定义了一个引用有效的作用域

https://www.cntofu.com/book/55/content/Lifetimes%20%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F.md

或者你可以这样

let mut x = 5;
let y = &x;
println!("{}", x);
println!("{}", y);
SunApriloy 2021-02-09 10:30

这个和借用规则有关,生命周期的话,x永远大于y的

--
👇
eric642:

fn main() {
    let mut x = 5;   -----------x的生命周期
    let y = &mut x;     =====y的生命周期
    println!("{}", y);  =====>end
    println!("{}", x);  -------->end
}
fn main() {
    let mut x = 5;  -----------x的生命周期
    let y = &mut x;    =====y的生命周期
    println!("{}", x);  -------->end
    println!("{}", y); =====>end
}

引用的生命周期不能小于被引用的.

gotope 2021-02-08 16:29

是可变借用不能同时访问,还是生命周期长度范围的问题?

eric642 2021-02-07 09:26
fn main() {
    let mut x = 5;   -----------x的生命周期
    let y = &mut x;     =====y的生命周期
    println!("{}", y);  =====>end
    println!("{}", x);  -------->end
}
fn main() {
    let mut x = 5;  -----------x的生命周期
    let y = &mut x;    =====y的生命周期
    println!("{}", x);  -------->end
    println!("{}", y); =====>end
}

引用的生命周期不能小于被引用的.

freedom967 2021-02-07 09:22

你的写法实际上违背了借用规则,x被可变借出后,在当前作用域下,你是不能再访问x的,因为这个违背了可变借用和不可变不能同时存在的原则,没错,x被借出后,原则上你是不能再访问x的。。。为什么调换顺序后可以,那是rust编译器的锅,因为他判断y在后面不再被使用(也就是可变借用到这里结束了),所以这时候你访问x是可以的,非词法作用域的功劳,简化了实际代码编写的。谨记rust的借用规则才是重点。

catsalwaysmeow 2021-02-07 06:16

不清楚这个资料有没有过时,可以参考一下:https://github.com/rust-lang/rfcs/blob/master/text/2094-nll.md

借用的生命周期是囊括了这个借用被使用的每一个时间点的最小范围。第一份代码中,打印x时,可变借用y仍然存活(因为之后还要打印y),那么x仍处于被借用中的冻结状态,所以报错了。第二份代码中,打印x时,y的生命周期已经结束了,因为它是一个借用。

1 共 8 条评论, 1 页