rust - 为什么当我用一个新值替换它时,Rust 编译器会抱怨我使用了一个移动的值?
问题描述
我正在研究两个单链表,名为longer
和shorter
. 一个的长度longer
保证不小于shorter
一个。
我将列表元素配对,并对每一对做一些事情。如果longer
列表中有更多未配对的元素,则处理其余元素:
struct List {
next: Option<Box<List>>,
}
fn drain_lists(mut shorter: Option<Box<List>>, mut longer: Option<Box<List>>) {
// Pair the elements in the two lists.
while let (Some(node1), Some(node2)) = (shorter, longer) {
// Actual work elided.
shorter = node1.next;
longer = node2.next;
}
// Process the rest in the longer list.
while let Some(node) = longer {
// Actual work elided.
longer = node.next;
}
}
但是,编译器在第二个 while 循环中抱怨
error[E0382]: use of moved value
--> src/lib.rs:13:20
|
5 | fn drain_lists(mut shorter: Option<Box<List>>, mut longer: Option<Box<List>>) {
| ---------- move occurs because `longer` has type `std::option::Option<std::boxed::Box<List>>`, which does not implement the `Copy` trait
6 | // Pair the elements in the two lists.
7 | while let (Some(node1), Some(node2)) = (shorter, longer) {
| ------ value moved here
...
13 | while let Some(node) = longer {
| ^^^^ value used here after move
但是,我确实shorter
在循环结束时为and设置了一个新值longer
,这样我就永远不会使用它们的移动值。
我应该如何迎合编译器?
解决方案
我认为问题是由第一个循环中的临时元组引起的。创建一个元组会将其组件移动到新元组中,即使随后的模式匹配失败也会发生这种情况。
首先,让我编写一个更简单的代码版本。这编译得很好:
struct Foo(i32);
fn main() {
let mut longer = Foo(0);
while let Foo(x) = longer {
longer = Foo(x + 1);
}
println!("{:?}", longer.0);
}
但是如果我添加一个临时的 while let
然后我会触发一个类似于你的编译器错误:
fn fwd<T>(t: T) -> T { t }
struct Foo(i32);
fn main() {
let mut longer = Foo(0);
while let Foo(x) = fwd(longer) {
longer = Foo(x + 1);
}
println!("{:?}", longer.0);
// Error: ^ borrow of moved value: `longer`
}
解决方案是添加一个带有要解构的值的局部变量,而不是依赖临时变量。在您的代码中:
struct List {
next: Option<Box<List>>
}
fn drain_lists(shorter: Option<Box<List>>,
longer: Option<Box<List>>) {
// Pair the elements in the two lists.
let mut twolists = (shorter, longer);
while let (Some(node1), Some(node2)) = twolists {
// Actual work elided.
twolists = (node1.next, node2.next);
}
// Process the rest in the longer list.
let (_, mut longer) = twolists;
while let Some(node) = longer {
// Actual work elided.
longer = node.next;
}
}
推荐阅读
- html-table - 可用于选择特定条件的可扩展表列有哪些最佳实践?
- java - 如何获取域的 SPF 和 TXT 记录?
- mysql - 如何从 2 个 MySQL 表中设计一个兼容性矩阵?
- regex - 使用正则表达式删除 "?show=false"
- typescript - 部分递归
不适用于泛型 - amazon-sagemaker - BlazingText jsonlines 批量转换的问题
- azure-devops - 在 Azure DevOps 中使用构建管道运行 Google 测试
- mysql - 我的查询没有返回当月工作时间总和的最大值
- java - 在活动开始时在循环中分配按钮的快速方法是什么?
- git - Github - 更新分支后同步分叉