我刚刚开始学习 Rust,虽然我确实有一些 C++ 经验(尽管它很生锈),所以我可以理解指针、引用和其他东西,但我似乎无法理解在我尝试它时出现的这个错误。
考虑以下代码:
let mut original = String::from("original value");
{
let next = &mut original;
*next = String::from("next value");
println!("\nInner scope original: \t\"{}\"", original); // <-- error here
println!("\nInner scope next: \t\"{}\"", next);
}
println!("\nOuter original value: \t\"{}\"", original);
Run Code Online (Sandbox Code Playgroud)
编译器抛出错误:
error[E0502]: cannot borrow `original` as immutable because it is also borrowed as mutable
| let next = &mut original;
| ------------- mutable borrow occurs here
| *next = String::from("next value");
| println!("\nInner scope original: \t\"{}\"", original);
| ^^^^^^^^ immutable borrow occurs here
| println!("\nInner scope next: \t\"{}\"", next);
| ---- mutable borrow later used here
|
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
Run Code Online (Sandbox Code Playgroud)
但如果我只像这样切换行的顺序:
error[E0502]: cannot borrow `original` as immutable because it is also borrowed as mutable
| let next = &mut original;
| ------------- mutable borrow occurs here
| *next = String::from("next value");
| println!("\nInner scope original: \t\"{}\"", original);
| ^^^^^^^^ immutable borrow occurs here
| println!("\nInner scope next: \t\"{}\"", next);
| ---- mutable borrow later used here
|
= note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
Run Code Online (Sandbox Code Playgroud)
...然后就可以正常工作了。这两者有什么不同,考虑到它们都不会改变任何东西,为什么编译器在一种情况下会抛出错误,而在另一种情况下不会抛出错误?
如果我尝试在变异之前打印该值,也会引发错误original:
let mut original = String::from("original value");
{
let next = &mut original;
*next = String::from("next value");
println!("\nInner scope next: \t\"{}\"", next);
println!("\nInner scope original: \t\"{}\"", original); // <-- no error
}
println!("\nOuter original value: \t\"{}\"", original);
Run Code Online (Sandbox Code Playgroud)
我相信对于那些有更多 Rust 经验的人来说,有一个明显的逻辑解释。
Rust 认为对的独占引用从创建它的那一行开始一直存在到next最后一次使用它。只要存在,就不能采用其他引用(共享或可变) ;这是借用检查的主要限制。打印内部使用对打印数据的共享引用,因此会出现错误。originalnextoriginal
这解释了当您交换某些行时,您会看到其中一些被拒绝的行现在已被接受,因为它们现在出现在上次使用next.
您可能会反对最后一次使用next不需要突变;这是真的,但规则是,只要独占引用存在,这种突变就可能发生。
请注意,您在代码中引入的大括号可能来自旧示例,当时生命周期分析依赖于范围;当时建议明确缩小范围,以减少潜在的冲突。现在,有一种非词法生命周期分析,可以自动缩小多次借用可能发生冲突的代码部分;这部分在最后一次使用引用时停止,而不是在范围末尾(这些大括号不再有用)。这就是你在交换线路时所经历的。
| 归档时间: |
|
| 查看次数: |
130 次 |
| 最近记录: |