这是我要执行的代码:
fn my_fn(arg1: &Option<Box<i32>>) -> i32 {
if arg1.is_none() {
return 0;
}
let integer = arg1.unwrap();
*integer
}
fn main() {
let integer = 42;
my_fn(&Some(Box::new(integer)));
}
我在以前的 Rust 版本中遇到以下错误:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:5:19
|
5 | let integer = arg1.unwrap();
| ^^^^ cannot move out of borrowed content
在更现代的版本中:
error[E0507]: cannot move out of `*arg1` which is behind a shared reference
--> src/main.rs:5:19
|
5 | let integer = arg1.unwrap();
| ^^^^
| |
| move occurs because `*arg1` has type `std::option::Option<std::boxed::Box<i32>>`, which does not implement the `Copy` trait
| help: consider borrowing the `Option`'s content: `arg1.as_ref()`
我看到已经有很多关于borrow checker问题的文档,但是看了之后,我还是没弄清楚问题所在。
为什么这是一个错误,我该如何解决?
最佳答案
Option::unwrap()
消耗选项,也就是说,它按值接受选项。但是,您没有值,您只有对它的引用。这就是错误的原因。
您的代码应该按照惯用的方式编写:
fn my_fn(arg1: &Option<Box<i32>>) -> i32 {
match arg1 {
Some(b) => **b,
None => 0,
}
}
fn main() {
let integer = 42;
my_fn(&Some(Box::new(integer)));
}
或者您可以使用 Option
组合器,例如 Option::as_ref
或 Option::as_mut
与 Option::map_or
配对,正如 Shepmaster 所建议的那样:
fn my_fn(arg1: &Option<Box<i32>>) -> i32 {
arg1.as_ref().map_or(0, |n| **n)
}
此代码使用了 i32
可自动复制的事实。如果 Box
中的类型不是 Copy
,那么您根本无法按值获取内部值 - 您只能克隆它或返回引用,例如,像这里:
fn my_fn2(arg1: &Option<Box<i32>>) -> &i32 {
arg1.as_ref().map_or(&0, |n| n)
}
由于您只有对选项的不可变引用,因此您只能返回对其内容的不可变引用。 Rust 足够聪明,可以将文字 0
提升为静态值以保留,以便在缺少输入值的情况下能够返回它。
关于rust - 展开时无法移出共享引用后面的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52954762/