在这个例子中,为什么我可以在匹配表达式中取消引用 t
而不是在正上方的行中?
fn tree_weight_v2(t: &BinaryTree) -> i32 {
// let x = *t; // if uncommented, error: "Cannot move out of borrowed content"
match *t {
BinaryTree::Leaf(payload) => payload,
BinaryTree::Node(ref left, payload, ref right) => {
tree_weight_v2(left) + payload + tree_weight_v2(right)
}
}
}
#[test]
fn tree_demo_2() {
let tree = sample_tree();
assert_eq!(tree_weight_v2(&tree), (1 + 2 + 3) + 4 + 5);
assert_eq!(tree_weight_v2(&tree), (1 + 2 + 3) + 4 + 5);
// no error ^ meaning tree_weight_v2 is not taking ownership of tree
}
enum BinaryTree {
Leaf(i32),
Node(Box<BinaryTree>, i32, Box<BinaryTree>)
}
fn sample_tree() -> BinaryTree {
let l1 = Box::new(BinaryTree::Leaf(1));
let l3 = Box::new(BinaryTree::Leaf(3));
let n2 = Box::new(BinaryTree::Node(l1, 2, l3));
let l5 = Box::new(BinaryTree::Leaf(5));
BinaryTree::Node(n2, 4, l5)
}
我认为代码在 match 语句之外所做的事情并不重要 - 当然,除非那是我困惑的根源。
我也很好奇匹配表达式如何处理取消引用的值。具体来说,由于匹配表达式看到的是 BinaryTree
类型的值(没有任何引用),为什么匹配表达式不尝试获取它的所有权?更一般地说,Rust 的 match
如何解释指向值的解引用指针与正常值之间的区别?
最佳答案
let x = *t
不起作用,因为它已移出引用。 IE。这意味着,通过取消引用 t
,您会得到一个 BinaryTree
(没有引用)。 BinaryTree
是在函数中借用的,所以用 let x = *t
赋值会将它移到 x 中,这是不可能的,因为它是借用的。
匹配确实有效,因为 match
借用了变量。 match *t
不会把它搬出去,但是会借用BinaryTree
。这是 Rust 中的一种特殊语法,借用发生在幕后。你可以这样想:
fn tree_weight_v2(t: &BinaryTree) -> i32 {
match &*t {
&BinaryTree::Leaf(payload) => payload,
&BinaryTree::Node(ref left, payload, ref right) => {
tree_weight_v2(left) + payload + tree_weight_v2(right)
}
}
}
但不需要所有引用。
另见:
关于reference - 匹配表达式如何解释值与引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51108873/