我尝试运行此代码:
impl FibHeap {
fn insert(&mut self, key: int) -> () {
let new_node = Some(box create_node(key, None, None));
match self.min{
Some(ref mut t) => t.right = new_node,
None => (),
};
println!("{}",get_right(self.min));
}
}
fn get_right(e: Option<Box<Node>>) -> Option<Box<Node>> {
match e {
Some(t) => t.right,
None => None,
}
}
Run Code Online (Sandbox Code Playgroud)
并得到错误
error: cannot move out of dereference of `&mut`-pointer
println!("{}",get_right(self.min));
^
Run Code Online (Sandbox Code Playgroud)
我不明白为什么我会遇到这个问题,以及我必须使用什么来避免问题.
Vla*_*eev 11
你的问题是get_right()接受Option<Box<Node>>,虽然它应该真的接受Option<&Node>并返回Option<&Node>.呼叫站点也应该适当更改.
这是解释.Box<T>是一个堆分配的框.它遵循值语义(也就是说,它的行为类似于普通,T除了它具有关联的析构函数,因此它总是被移动,永远不会被复制).因此,只是传递Box<T>到一个函数意味着放弃价值的所有权和移动入功能.但是,这不是你真正想要的,也不能在这里做.get_right()函数只查询现有结构,因此不需要所有权.如果不需要所有权,那么引用就是答案.此外,它仅仅是不可能移动self.min到一个函数,因为self.min是通过存取self,这是一个借用的指针.但是,您无法从借来的数据中移出,这是编译器提供的基本安全保证之一.
将您的get_right()定义更改为以下内容:
fn get_right(e: Option<&Node>) -> Option<&Node> {
e.and_then(|n| n.right.as_ref().map(|r| &**r))
}
Run Code Online (Sandbox Code Playgroud)
然后println!()应该将呼叫改为:
println!("{}", get_right(self.min.map(|r| &**r))
Run Code Online (Sandbox Code Playgroud)
这是这里发生的事情.为了获得Option<&Node>从Option<Box<Node>>您需要将"转换"适用于原来的内部Option.确实存在一种方法,称为map().但是,map()按值取目标,这意味着Box<Node>进入关闭状态.然而,我们只希望借用Node,所以首先我们需要去Option<Box<Node>>到Option<&Box<Node>>为了map()工作.
Option<T>有一个方法,as_ref()它通过引用获取其目标并返回Option<&T>一个对选项内部的可能引用.在我们的例子中,它将是Option<&Box<Node>>.现在这个值可以安全地map()过去,因为它包含一个引用,并且引用可以自由移动而不会影响原始值.
所以,接下来,map(|r| &**r)是从转换Option<&Box<Node>>到Option<&Node>.如果选项存在,则闭包参数应用于选项的内部,否则None只是通过.&**r应该从内到外阅读:&(*(*r))也就是说,首先我们取消引用&Box<Node>,获取Box<Node>,然后我们取消引用后者,获得公正Node,然后我们引用它,最后得到&Node.由于这些参考/解除引用操作并列,因此不涉及移动/复制.所以,我们得到了一个可选的参照Node,Option<&Node>.
你可以看到类似的事情发生在get_right()功能上.但是,还有一种新的方法and_then()叫做.它等同于你get_right()最初编写的内容:如果它的目标是None,则返回None,否则返回Option作为其参数传递的-returning闭包的结果:
fn and_then<U>(self, f: |T| -> Option<U>) -> Option<U> {
match self {
Some(e) => f(e),
None => None
}
}
Run Code Online (Sandbox Code Playgroud)
我强烈建议阅读官方指导其解释了所有权和借贷,以及如何使用它们,因为这些都是锈语言的根本基础,掌握他们为了生产具有防锈是非常重要的.