请考虑以下代码:
fn print_or(opt:Option<()>, tail:Vec<i32>)-> Vec<i32> { opt.map_or(tail, |_| { println!("{:?}", tail); tail })}
错误信息显示:
error[E0382]: use of moved value: `tail` --> src/lib.rs:2:22 |1 | fn print_or(opt:Option<()>, tail:Vec<i32>)-> Vec<i32> { | ---- 移动发生的原因是 `tail` 的类型是 `Vec<i32>`,它没有实现 `Copy` 特性2 | opt.map_or(tail, |_| { | ---- ^^^ 值在移动后用于此处 | | | | 值在此处移动3 | println!("{:?}", tail);4 | tail | ---- 由于在闭包中使用,因此会发生使用 |help: consider cloning the value if the performance cost is acceptable |2 | opt.map_or(tail.clone(), |_| { | ++++++++
而且很明显,因为我在这里使用了拥有的
Vec<i32>
类型。但问题是,由于
Option
不能同时是
Some
和
None
,所以很明显它不能在 move 之后使用。有没有办法在没有
clone
或
Rc
的情况下解决这个问题?
是对的,
Option
不能同时是
Some
和
None
,因此不能在移动后使用。这里的关键是理解
map_or
方法是如何工作的。
map_or
方法接受两个参数:
-
一个默认值(在你的例子中是
tail
) -
一个闭包,如果
Option
是Some
,则使用Some
中的值调用该闭包
问题在于,如果
Option
是
Some
,
map_or
需要
移动
默认值到闭包中。这是因为闭包可能会修改这个值,并且 Rust 确保只在一个地方拥有一个值的所有权。
在你的代码中,即使闭包没有修改
tail
,它仍然需要移动所有权。这就是为什么你得到 "use of moved value" 错误的原因。
为了解决这个问题,你可以借用
tail
给闭包,而不是移动它:
fn print_or(opt: Option<()>, tail: Vec<i32>) -> Vec<i32> {
opt.map_or(tail, |_| {
println!("{:?}", &tail); // 使用 &tail 借用 tail
tail
})
}
在这个修改后的代码中:
-
println!("{:?}", &tail);
使用&tail
借用了tail
,而不是获取它的所有权。 -
由于
tail
只是被借用,而不是被移动,因此它可以在map_or
的两个分支中使用。
这个解决方案避免了克隆或使用
Rc
,同时仍然满足 Rust 的所有权规则。