gpt4 book ai didi

rust - 调用 Option::unwrap 时无法移出 `&mut` 指针的取消引用

转载 作者:行者123 更新时间:2023-11-29 08:11:48 24 4
gpt4 key购买 nike

以下代码无法编译:

struct Node {
left: Option<Box<Node>>,
right: Option<Box<Node>>,
}

impl Node {
fn new() -> Node {
Node { left: None, right: None, }
}
}

fn init_tree(root: &mut Box<Node>, n: int) {
match n {
0 => {},
_ => {
root.left = Some(box Node::new());
root.right = Some(box Node::new());
init_tree(&mut root.left.unwrap(), n - 1);
init_tree(&mut root.left.unwrap(), n - 1);
}
}
}

fn main() {
let mut root: Box<Node> = box Node::new();
init_tree(&mut root, 10);
}

编译错误是

error: cannot move out of dereference of `&mut`-pointer
init_tree(&mut root.left.unwrap(), n - 1);
^~~~

我该如何解决这个错误?

最佳答案

Rust 编译器不假装出类拔萃的学术成就;它完全按照您告诉的去做,而不是您的意思或想要的。

在这种情况下,当您说 &mut root.left.unwrap() ,你想要的是需要 Option<Box<Node>> 的东西通过可变引用并给你一个 &mut Box<Node> ;但这绝对不是您实际告诉它要做的。

您告诉它要做的是对 root.left.unwrap() 的结果进行可变引用。 ;让我们看看 Option.unwrap 的签名:

fn unwrap(self) -> T

那又如何root.left.unwrap()消耗 root.left 吗? ,取而代之的是 Box<Node>对象(或者 panic ,如果它是 None )。然后剩下整个表达式 &mut root.left.unwrap()生产 &mut Box<Node> , 和消耗 root.left 因此部分 root .现在绝对不允许您这样做,因为它会留下 root需要被销毁,但你只有一个可变的引用它 - 它不是你的销毁。因此错误。

解决方案是不使用unwrap而是写一个合适的match表达自己。记住,.unwrap()只是match self { Some(x) => x, None => panic!(…) } ,这没什么神奇的。

你最终会得到这样的结果:

fn init_tree(root: &mut Node, n: int) {
if n != 0 {
root.left = Some(box Node::new());
root.right = Some(box Node::new());
init_tree(match root.left { Some(box ref mut x) => x, None => unreachable!() }, n - 1);
init_tree(match root.right { Some(box ref mut x) => x, None => unreachable!() }, n - 1);
}
}

(恐怕 box ref mut x 部分有点困惑;它从 &mut T 生成 Box<T>box 表示“拆箱值”,ref mut 表示“然后对其进行可变引用”。请记住,所有内容都是从前到后的模式,box& 的含义与它们在外部所做的相反,并且所有内容都是从左到右而不是从右到左阅读. 此外,虽然您可以使用 &mut Box<Node>,但我建议您使用 &mut Node,这样可以消除一级间接访问。顺便说一句,如果您仍在使用 &mut Box<Node>root.left.as_mut().unwrap() 也可以.)

这可以通过不把东西塞进 root 来改善。立即:

fn init_tree(root: &mut Node, n: int) {
if n != 0 {
let mut left = box Node::new();
let mut right = box Node::new();
init_tree(&mut *left, n - 1);
init_tree(&mut *right, n - 1);
root.left = Some(left);
root.right = Some(right);
}
}

这样看起来就简单多了,&mut *left从右到左阅读为“解引用 left (这将使您从 Node 得到一个 Box<Node> )然后对其进行可变引用(这将使您得到一个 &mut Node )。

关于rust - 调用 Option::unwrap 时无法移出 `&mut` 指针的取消引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27687872/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com