"Ejdrien answers"展示了可变和不可变借用之间的区别,但它并没有解决您问题中的一个小标题,即您正在执行作为
模式匹配的一部分的借用。
当您编写:
let (mut part1, mut part2) = someTuple;
您正在通过
移动它们,将
someTuple
的内容绑定到可变变量
part1
和
part2
。除非
someTuple
的内容是
Copy
able的,否则变量
part1
和
part2
将成为各自值的独占所有者。如果您尝试以后写入访问
someTuple
,例如:
println!("{}", someTuple.0);
如果您从借用检查器中收到类似的编译错误:
error[E0382]: borrow of moved value: `someTuple.0`
--> main.rs:6:20
|
4 | let (mut part1, mut part2) = someTuple;
| --------- value moved here
5 |
6 | println!("{}", someTuple.0);
| ^^^^^^^^^^^ value borrowed here after move
在这种特定的情况下,有两种方法可以通知编译器我们只想借用 someTuple
的内容。第一种方法是 Ejdrien 描述的技术,即显式地借用元组,然后对结果引用执行模式匹配:
// Produce two mutable references
let (part1, part2) = &mut someTuple;
// Produce two immutable references
let (part1, part2) = &someTuple;
这种方法的问题在于我们被迫以同样的方式借用
全部内容。如果我们只需要对
someTuple.0
进行可变引用,并且想要将
someTuple.1
作为副本或者不可变引用检索出来,怎么办?对于这个元组示例来说,这可能不太重要,但是对于更复杂的模式匹配情况,拥有这种类型的控制就更加重要了。
这带我们来到第二个解决方案:绑定引用。我们可以写成如下形式,而不是上面所述的方式。
// Produce two mutable references
let (ref mut part1, ref mut part2) = someTuple;
// Produce two immutable references
let (ref part1, ref part2) = someTuple;
在这里,我们明确说明了如何绑定模式匹配中的每个变量。关键在于我们可以自由地混合可变和不可变的借用,因此以下内容也完全有效:
let (ref part1, ref mut part2) = someTuple;
println!("{}", &someTuple.0);
*part2 = ...
println!("{}", part1);
如果我们将上述内容替换为右侧的显式可变借用,由于同时存在可变和不可变引用,我们将再次从借用检查器中收到错误提示:
let (part1, part2) = &mut someTuple;
println!("{}", &someTuple.0);
*part2 = ...
println!("{}", part1);
生产
error[E0502]: cannot borrow `someTuple.0` as immutable because it is also borrowed as mutable
--> main.rs:6:20
|
4 | let (part1,part2) =&mut someTuple;
| -------------- mutable borrow occurs here
5 |
6 | println!("{}", &someTuple.0);
| ^^^^^^^^^^^^ immutable borrow occurs here
...
9 | println!("{}", part1);
| ----- mutable borrow later used here
error: aborting due to previous error
y2
是在最后一次使用y1
之后声明的,所以第二个可变借用是允许的,因为作用域从未重叠。只有当您尝试在对y2
进行可变借用之后使用y1
时,此示例才会被借用检查器拒绝。您的第二个示例也是如此--实际上,您列出的所有“非法”借用在 Rust 中都是完全允许的。 - Brian61354270