当拆包时,不能从共享引用后面的值中移出。

问题描述 投票:14回答:1

这是我试图执行的代码。

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

我看到已经有很多关于借贷检查器问题的文档了 但在阅读之后,我还是无法理解这个问题。

为什么会出现这样的错误,我该如何解决?

rust borrow-checker
1个回答
16
投票

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_refOption::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 变成一个静态值来保存,以便在没有输入值的情况下能够返回它。

© www.soinside.com 2019 - 2024. All rights reserved.