Rust 所有权 - 由于 "behind a shared reference" 而无法移动
Rust ownership - cannot move due to being "behind a shared reference"
我正在学习 Rust 并在链表上练习,因此我想找到一个不涉及最后 .clone()
的解决方案。
这是我能想到的最小的有用 MVP 代码 (Rust Playground):
#![allow(unused)]
fn main() {
let v: Option<Box<ListNode>> = None;
println!("{:?}", v);
let result2 = get_nth_node(v, 3);
println!(" --> {:?}", result2);
}
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
pub val: i32,
pub next: Option<Box<ListNode>>
}
fn get_nth_node(head: Option<Box<ListNode>>, n:usize) -> Option<Box<ListNode>> {
if head.is_none() {
return None;
}
let mut count = 1;
let mut ptr: &Option<Box<ListNode>> = &head;
while count < n {
count += 1;
match ptr {
None => return None,
Some(v) => ptr = &v.next
}
}
return (*ptr);
}
这会在移动和借用时产生错误:
error[E0507]: cannot move out of `*ptr` which is behind a shared reference
--> src/main.rs:30:12
|
30 | return (*ptr);
| ^^^^^^
| |
| move occurs because `*ptr` has type `std::option::Option<std::boxed::Box<ListNode>>`, which does not implement the `Copy` trait
| help: consider borrowing the `Option`'s content: `(*ptr).as_ref()`
我理解为什么将函数更改为 return (*ptr).clone()
有效,但它似乎是多余的。
我的两个主要问题:
*ptr
后面的共享引用具体是什么?
- 从概念上讲,有没有更好的方法在 Rust 中使用它?
What specifically is the shared reference that *ptr is behind?
ptr
是共享(不可变)引用:
let mut ptr: &Option<Box<ListNode>> = &head;
*ptr
在该引用后面。
Is there a better way, conceptually, to work with this in Rust?
好吧,你可以不使用引用,因为你是按值获取列表并因此使用它:
fn get_nth_node(mut head: Option<Box<ListNode>>, n:usize) -> Option<Box<ListNode>> {
let mut count = 1;
while count < n {
count += 1;
match head {
None => return None,
Some(v) => head = v.next
}
}
return head;
}
或者,您可以使用 refs(这可能是一个更好的主意):
fn get_nth_node(mut head: Option<&ListNode>, n:usize) -> Option<&ListNode> {
let mut count = 1;
while count < n {
count += 1;
match head {
None => return None,
Some(v) => head = v.next.as_ref().map(Box::as_ref)
}
}
head
}
我正在学习 Rust 并在链表上练习,因此我想找到一个不涉及最后 .clone()
的解决方案。
这是我能想到的最小的有用 MVP 代码 (Rust Playground):
#![allow(unused)]
fn main() {
let v: Option<Box<ListNode>> = None;
println!("{:?}", v);
let result2 = get_nth_node(v, 3);
println!(" --> {:?}", result2);
}
#[derive(PartialEq, Eq, Clone, Debug)]
pub struct ListNode {
pub val: i32,
pub next: Option<Box<ListNode>>
}
fn get_nth_node(head: Option<Box<ListNode>>, n:usize) -> Option<Box<ListNode>> {
if head.is_none() {
return None;
}
let mut count = 1;
let mut ptr: &Option<Box<ListNode>> = &head;
while count < n {
count += 1;
match ptr {
None => return None,
Some(v) => ptr = &v.next
}
}
return (*ptr);
}
这会在移动和借用时产生错误:
error[E0507]: cannot move out of `*ptr` which is behind a shared reference
--> src/main.rs:30:12
|
30 | return (*ptr);
| ^^^^^^
| |
| move occurs because `*ptr` has type `std::option::Option<std::boxed::Box<ListNode>>`, which does not implement the `Copy` trait
| help: consider borrowing the `Option`'s content: `(*ptr).as_ref()`
我理解为什么将函数更改为 return (*ptr).clone()
有效,但它似乎是多余的。
我的两个主要问题:
*ptr
后面的共享引用具体是什么?- 从概念上讲,有没有更好的方法在 Rust 中使用它?
What specifically is the shared reference that *ptr is behind?
ptr
是共享(不可变)引用:
let mut ptr: &Option<Box<ListNode>> = &head;
*ptr
在该引用后面。
Is there a better way, conceptually, to work with this in Rust?
好吧,你可以不使用引用,因为你是按值获取列表并因此使用它:
fn get_nth_node(mut head: Option<Box<ListNode>>, n:usize) -> Option<Box<ListNode>> {
let mut count = 1;
while count < n {
count += 1;
match head {
None => return None,
Some(v) => head = v.next
}
}
return head;
}
或者,您可以使用 refs(这可能是一个更好的主意):
fn get_nth_node(mut head: Option<&ListNode>, n:usize) -> Option<&ListNode> {
let mut count = 1;
while count < n {
count += 1;
match head {
None => return None,
Some(v) => head = v.next.as_ref().map(Box::as_ref)
}
}
head
}