Rust 在“中匹配可变选项引用”之间有什么区别;如果让一些(参考mut x)=选项;及;如果让某些(x)=选项.as_mut()“;? 背景
考虑一个玩具问题,其中我有一个表示链表节点的Rust 在“中匹配可变选项引用”之间有什么区别;如果让一些(参考mut x)=选项;及;如果让某些(x)=选项.as_mut()“;? 背景,rust,reference,mutable,Rust,Reference,Mutable,考虑一个玩具问题,其中我有一个表示链表节点的节点结构,我想创建一个函数来构建一个值为1到9的列表。以下代码按预期工作: struct Node { val: i32, next: Option<Box<Node>>, } fn build_list() -> Option<Box<Node>> { let mut head = None; let mut tail = &mut head; f
节点
结构,我想创建一个函数来构建一个值为1到9的列表。以下代码按预期工作:
struct Node {
val: i32,
next: Option<Box<Node>>,
}
fn build_list() -> Option<Box<Node>> {
let mut head = None;
let mut tail = &mut head;
for n in 1..10 {
*tail = Some(Box::new(Node {val: n, next: None}));
if let Some(ref mut x) = tail {
tail = &mut x.next;
};
}
head
}
编译错误:
错误[E0506]:无法分配给“*tail”,因为它是借用的
-->src/main.rs:72:9
|
72 |*tail=Some(Box::new(节点{val:n,next:None}));
| ^^^^^
| |
|借来的“*tail”的赋值发生在此处
|借来以后用在这里
73 | {
74 |如果让一些(x)=尾{
|----此处借用“*tail”
错误[E0499]:一次不能将“*tail”作为可变项借用多次
-->src/main.rs:74:30
|
74 |如果让一些(x)=尾{
|^^^^可变借用在循环的上一次迭代中从这里开始
问题:
在这个例子中,两者的区别是什么
if let Some(ref mut x) = tail
及
?
(作为一个学习锈菌的初学者)我本以为这些匹配表达式是等价的,但显然我忽略了一些细微的差别
更新
我从我的原始示例中清理了代码,因此我不需要为列表的开头添加占位符元素。区别(和编译错误)仍然存在,我只是在分配给借用的*tail
时得到了一个额外的编译错误
更新2
(这只是一个奇怪的观察,无助于回答最初的问题)
在考虑了@Emoun的答案之后,编译器应该能够知道tail
在循环的每次迭代中都在变化(这样它就可以确保每次借用的&mut x.next
是不同的),这听起来很重要(在第一个工作示例中)。因此,我做了一个实验,通过在tail=&mut x.next;
赋值中添加一个if n%2==0
条件来更改代码,使编译器无法判断情况是否如此。果然,这导致了一个与另一个类似的编译错误:
fn build_list() -> Option<Box<Node>> {
let mut head = None;
let mut tail = &mut head;
for n in 1..10 {
*tail = Some(Box::new(Node {val: n, next: None}));
if let Some(ref mut x) = tail {
if n % 2 == 0 {
tail = &mut x.next;
}
};
}
head
}
代码的第二个版本失败的原因是rust的方法/函数总是借用整个对象,而不是它们的一部分 在您的案例中,这意味着
tail.as_mut()
可变地借用tail
,并且只要使用tail
,此借用将保持有效:
。。。
对于1..10中的n{
*tail=Some(Box::new(Node{val:n,next:None}));//第二次迭代中出错,
//“尾巴”已经被借用了
if let Some(x)=tail.asmut(){/if let Some(x)=tail
似乎也能工作。不幸的是,我没有对任何情况的解释。似乎tail.asmut()的返回值的生存期
与tail
相同,因此只是一个编译器限制。在循环中移动让tail=&mut head
使其工作。看起来非常相似。任何想知道为什么Some(x)
可以匹配&mut选项类型的人都应该查找。@CoronA,如果让Some(x)=tail
确实有效,这也让我感到惊讶(学到了一些新东西,谢谢!)。这仍然不能解释为什么它与tail=&mut head
(而不是&mut x.next
)一起作为的
case。如果你这样做,我认为程序的逻辑是不一样的。但是,它确实可以编译,因为如果你把所有尾部都分配给head
,你就永远不会有tail
借用它自己,它们都会借用head
。我相信逻辑不是这个例子的重点,我也不认为借用它自己是一个正确的参数,由于tail
是一个指针,tail
的指针对象将在调用tail后被重新借用。as_mut()
,那么tail
将以可变方式借用x。接下来将以可变方式借用。所有这些是x
可以多次借用(而不是tail
)。如果您使用tail=&mut head
我们的x
将成为head
,并且head
将作为可变项被多次借用,那么为什么它允许多次借用head呢?@luca_mollerx
在每个迭代中都是不同的变量,因为您使用If let-let-If-let(参考mut x)创建了一个新的变量=tail
。因此,没有连接到从一个迭代到下一个迭代的x
的借用。是的,借用x
允许编译器看到没有从一个迭代到下一个迭代的借用。感谢您让我知道借用检查器有更多的功能:)…只需将作为mut
忽略即可,&mut*tail
也违反了与as_mut()
相同的借用检查器规则。
if let Some(x) = tail.as_mut()
fn build_list() -> Option<Box<Node>> {
let mut head = None;
let mut tail = &mut head;
for n in 1..10 {
*tail = Some(Box::new(Node {val: n, next: None}));
if let Some(ref mut x) = tail {
if n % 2 == 0 {
tail = &mut x.next;
}
};
}
head
}