Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 无法移出对`&;的取消引用;调用Option::unwrap时的mut`-指针_Rust - Fatal编程技术网

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

Rust 无法移出对`&;的取消引用;调用Option::unwrap时的mut`-指针,rust,Rust,以下代码未编译: 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)

以下代码未编译:

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);
}

我怎样才能纠正这个错误呢?

铁锈编译器并不自诩智力卓越或学术崇高;它完全按照你告诉它的去做,而不是你的意思或想要的

在本例中,当您说
&mut root.left.unwrap()
时,您想要的是通过可变引用获取
选项
,并为您提供一个
&mut框
;但这绝对不是你让它做的

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

所以
root.left.unwrap()
所做的是它消耗
root.left
,产生一个
对象(如果它是
,则会惊慌失措)。然后剩下整个表达式
&mut root.left.unwrap()
生成
&mut Box
,并使用
root.left
,从而部分使用
root
。现在,您肯定不允许这样做,因为它会留下需要销毁的
root
,但是您只有一个可变的引用,它不是您要销毁的。因此出现了错误

解决方法不是使用
展开
,而是自己编写一个合适的
匹配
表达式。记住,
.unwrap()
只是
匹配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
部分有点纠结;它从
box
生成一个
&mut
box
表示“取消对值的装箱”,而
ref mut
表示“然后对其进行可变引用”。请记住,在模式中,所有内容都是从后到前的,
&
意味着与它们在外部所做的相反,整个批次从左到右读取,而不是从右到左读取。此外,虽然您可以使用
&mut框
,但我建议使用
&mut节点
,这样可以删除一个级别的间接。顺便说一句,如果您仍在使用
&mut Box
root.left.as_mut().unwrap()
也可以。)

这可以通过不立即将内容填充到
根目录中来改进:

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
(这将从
框中获取
节点
),然后获取对它的可变引用(这将获取
&mut节点
).

Rust编译器并不自诩为知识卓越或学术崇高;它完全按照你告诉它的去做,而不是按照你的意思或想要的去做

在本例中,当您说
&mut root.left.unwrap()
时,您想要的是通过可变引用获取
选项
,并为您提供一个
&mut框
;但这绝对不是您实际告诉它的

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

所以
root.left.unwrap()
所做的是它消耗
root.left
,产生一个
对象(或者如果它是
),那么就剩下整个表达式
和mut root.left.unwrap()
生成
&mut-Box
,并使用
根目录。左
,因此部分
根目录
。现在绝对不允许这样做,因为这样会使
根目录
需要销毁,但您只有一个对它的可变引用,它不是您要销毁的。因此出现了错误

解决方法不是使用
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
部分有点纠结;它从
box
生成一个
&mut
box
表示“取消对值的装箱”,而
ref mut
表示“然后对其进行可变引用”。请记住,在模式中,所有内容都是从后到前的,
&
意味着与它们在外部所做的相反,整个批次从左到右读取,而不是从右到左读取。此外,虽然您可以使用
&mut框
,但我建议使用
&mut节点
,这样可以删除一个级别的间接。顺便说一句,如果您仍在使用
&mut Box
root.left.as_mut().unwrap()
也可以。)

这可以通过不立即将内容填充到
根目录中来改进:

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
(这将从
框中获取
节点
),然后获取对它的可变引用(这将获取
&mut节点
).

上面的代码应该是这样的:let mut left=…;let mut right=…;无论如何,你的答案很好。谢谢!是的,我确实忘记了
mut
,如果你想改变值,就需要它。修改,谢谢!上面的代码应该是这样的:let mut left=…;let mut right=…;不管怎样,你的答案是太好了。谢谢!是的,我确实忘记了那里的
mut
,如果您希望对值进行变异,那么这是必需的。修改,谢谢!仅供参考,您的代码将
初始化两次;我希望这不会让您感到惊讶!^ ^仅供参考,您的代码将
初始化两次;我希望您不会感到惊讶^_^