#rust
Вопрос:
Я пытался реализовать односвязный список, имитируя реализацию стандартного связанного списка rust, и столкнулся с ошибкой при реализации pop_front
метода.
Код, который я изучал в rust, находится здесь, например:
fn pop_front_node(amp;mut self) -> Option<Box<Node<T>>> {
// This method takes care not to create mutable references to whole nodes,
// to maintain validity of aliasing pointers into `element`.
self.head.map(|node| unsafe {
let node = Box::from_raw(node.as_ptr()); // 1.
self.head = node.next; // 2.
match self.head {
None => self.tail = None,
// Not creating new mutable (unique!) references overlapping `element`.
Some(head) => (*head.as_ptr()).prev = None,
}
self.len -= 1;
node // 3.
})
}
Насколько мне известно, node
в строке 1 находится Box<Node<T>>
объект, который частично перемещен ( next
поле) self.head
в строку 2, а затем возвращен в строке 3 в качестве целого node
объекта также путем перемещения, что также должно быть перемещением после частичного перемещения и, возможно, не удалось скомпилировать? Но это должно работать так, как в стандартной библиотеке.
Код, который я писал, выглядит следующим образом и страдает от ошибки «значение, используемое после частичного перемещения». Полный фрагмент на странице playgound здесь.
fn pop_front(amp;mut self) -> Option<Box<Node<T>>> {
self.head.map(|node| unsafe {
// let node = Box::from_raw(node.as_ptr());
// let node = Box::from_raw(Box::into_raw(node));
// let node = Box::into_raw(node);
self.head = node.next;
node
})
}
Не мог бы кто-нибудь, пожалуйста, объяснить это и дать какие-либо решения о том, как исправить ошибку? Большое спасибо.
Комментарии:
1. Вероятно, вы могли бы реализовать необходимые функции без небезопасного кода. Я еще не пробовал внедрять связанные списки. idk, если это просто неизбежная деталь с ними, но, как правило, есть способы избежать небезопасности. Например, совместное использование ссылок на объекты обычно решается с помощью интеллектуальных указателей.
2. @Elinx
head
-это аNonNull<Node>
, а не аBox
.NonNull
по сути, это необработанный изменяемый указатель (только тот, который не должен быть нулевым). Как таковой, он естьCopy
(он же необработанные указатели могут быть псевдонимами), чего не происходитBox
.3. @Masklinn Спасибо , что указал на разницу между
NonNull
иBox
, но я думаюhead
, что это объект типаOption<NonNull<Node>
и так и естьnode.next
, ознакомьтесь с определением здесь , два варианта не могутCopy
друг другу подходить, так что я все ещеMove
думаю?4.
Option<T>
естьCopy
, еслиT
естьCopy
: doc.rust-lang.org/std/option/enum. Опция.html#impl-Копировать5. Обязательное чтение, если вы еще этого не сделали: Изучите Rust Со Слишком Большим Количеством Связанных Списков .