19

这是我试图执行的代码:

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()`

我看到已经有很多关于借用检查器问题的文档,但是在阅读之后,我仍然无法弄清楚问题所在。

为什么这是一个错误,我该如何解决?

4

2 回答 2

20

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)));
}

在锈操场上

或者您可以使用像Shepmaster 建议的Option组合器Option::as_refOption::as_mut与 配对:Option::map_or

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为静态值以保留,以便在没有输入值的情况下能够返回它。

于 2015-09-01T18:55:55.050 回答
1

由于 Rust 1.40 有Option::as_deref,所以现在你可以这样做:

fn my_fn(arg1: &Option<Box<i32>>) -> i32 {
    *arg1.as_deref().unwrap_or(&0)
}
于 2021-07-11T07:12:14.183 回答