Не может выйти из заимствованного контента при попытке передачи права собственности
Я пишу связанный список, чтобы обернуть свою голову вокруг времени жизни Rust, владения и ссылок. У меня есть следующий код:
pub struct LinkedList {
head: Option<Box<LinkedListNode>>,
}
pub struct LinkedListNode {
next: Option<Box<LinkedListNode>>,
}
impl LinkedList {
pub fn new() -> LinkedList {
LinkedList { head: None }
}
pub fn prepend_value(&mut self) {
let mut new_node = LinkedListNode { next: None };
match self.head {
Some(ref head) => new_node.next = Some(*head),
None => new_node.next = None,
};
self.head = Some(Box::new(new_node));
}
}
fn main() {}
Но я получаю следующую ошибку компиляции:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:18:52
|
18 | Some(ref head) => new_node.next = Some(*head),
| ^^^^^ cannot move out of borrowed content
Я думаю, что узел head
в настоящее время должен принадлежать self
, который является связанным списком. Когда я назначу его new_node.next
, вероятно, произойдет смена владельца.
Я бы предпочел не клонировать значение, если это возможно, поскольку это кажется расточительным. Я не хочу просто ... "одолжите" его на время выполнения функции. Я очень хочу передать его в собственность.
Как мне это сделать?
Я уже рассматривалошибку: не могу выйти из заимствованного содержания на &mut self ине могу выйти из заимствованного содержания .
Я попытался удалить руку соответствия, как было предложено в принятом ответе на один из этих вопросов, и определить next
при создании нового LinkedListNode
, но я получаю то же самое сообщение об ошибке.
У меня есть успешно добавлен метод append
, который принимает LinkedListNode
для добавления в конец списка.
1 ответ:
Не может выйти из заимствованного контента при попытке передачи права собственности
На высоком уровне, это против-зерна для ржавчины. Вы не можете передать собственность на что-то заимствованное , потому что вы не владеете этим. Вы не должны одалживать мою машину (
&Car
), а затем отдавать ее первому встречному на улице! Это по-прежнему верно, даже если я одолжу вам свою машину и позволю внести в нее изменения (&mut Car
).Вы не можете переместить
head
из&self
вообще потому что вы не можете изменить значение.Вы не можете переместить
head
из&mut self
, потому что это оставит структуруLinkedList
в несогласованном состоянии - одно из полей будет иметь неопределенное значение. Это основная мера гарантий безопасности ржавчины.В общем случае вам нужно будет следовать чему-то из как я могу поменять новое значение для поля в изменяемой ссылке на структуру? заменить существующее значение.
В этом случае вы можете использовать
Option::take
. Это позволит оставить переменную там, где она есть, изменив ее наNone
и вернув Предыдущее значение. Затем вы можете использовать это значение для построения новой главы списка:Более общее решение состоит в том, чтобы взять в собственность структуру, а не заимствовать ее. Это позволяет вам делать с ним все, что вы захотите. Заметим, что мы беремpub fn prepend_value(&mut self) { let head = self.head.take(); self.head = Some(Box::new(LinkedListNode { next: head })); }
self
по значению, а не по ссылке:pub fn prepend_value(mut self) -> LinkedList { self.head = Some(Box::new(LinkedListNode { next: self.head })); self }