頭を包み込むようにリンクリストを書いています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
Rustの新しいバージョンには、わずかに異なるエラーがあります:
error[E0507]: cannot move out of `*head` which is behind a shared reference
--> src/main.rs:18:52
|
18 | Some(ref head) => new_node.next = Some(*head),
| ^^^^^ move occurs because `*head` has type `std::boxed::Box<LinkedListNode>`, which does not implement the `Copy` trait
現在、head
ノードはリンクリストであるself
が所有している必要があると思います。それをnew_node.next
に割り当てると、おそらく所有権の変更が発生します。
無駄に思えるので、可能であれば値のクローンを作成したくありません。関数の期間中、単に「借りる」ことはしたくありません。私は本当にその所有権を譲渡したいと思います。
それ、どうやったら出来るの?
私はすでに &mut selfメソッドでメンバー変数をアンラップするときに借用コンテンツから移動できない および 借用コンテンツから移動できない/共有参照の背後から移動できない =。
それらの質問の1つで受け入れられた回答で提案されているようにマッチアームを削除し、新しいnext
の作成でLinkedListNode
を定義しようとしましたが、同じエラーメッセージが表示されます。
append
を使用してリストの最後に追加するLinkedListNode
メソッドを正常に追加しました。
所有権を譲渡しようとすると、借用したコンテンツから移動できません
大まかに言えば、これはRustにとっては正反対です。借りたものを所有していないため、所有権を譲渡することはできません。私の車(&Car
)を借りて、通りで最初に見た人に渡してはいけません。私があなたに私の車を貸して、あなたがそれを変更することを許可したとしても、これはまだ真実です(&mut Car
)。
値を変更できないため、head
を&self
から移動することはできません。
head
を&mut self
から移動することはできません。これは、LinkedList
構造体が一貫性のない状態のままになるためです。フィールドの1つに未定義の値があります。これは、Rustの安全保証の中核となる手段です。
一般に、既存の値を置き換えるには、 構造体への可変参照内のフィールドの新しい値をスワップするにはどうすればよいですか? から何かに従う必要があります。
この場合、 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
}