匹配选项时,`Some(&a)=> a`和`Some(a)=> * a`有什么区别?

时间:2018-06-26 13:51:31

标签: rust borrowing

为什么通过:

fn f(v: Vec<isize>) -> (Vec<isize>, isize) {
    match v.get(0) {
        Some(&a) => (v, a),
        _ => (v, 0)
    }
}

Playground

但这不是吗?:

fn f(v: Vec<isize>) -> (Vec<isize>, isize) {
    match v.get(0) {
        Some(a) => (v, *a),
        _ => (v, 0)
    }
}

Playground

error[E0505]: cannot move out of `v` because it is borrowed
 --> src/main.rs:7:21
  |
6 |     match v.get(0) {
  |           - borrow of `v` occurs here
7 |         Some(a) => (v, *a),
  |                     ^ move out of `v` occurs here

2 个答案:

答案 0 :(得分:1)

v.get(0)返回对向量中元素的引用,因此您正在匹配&isizeVec现在在匹配臂中借用了。

在第一个代码段中,您复制了isize,因此这里没有借用Vec。在第二个片段中,Vec仍然是借用的,因此您不能将其移出范围。

但是,您应该考虑使用if letunwrap_or

fn f(v: Vec<isize>) -> (Vec<isize>, isize) {
    let a = v.get(0).cloned();
    (v, a.unwrap_or(0))
}

Playground

fn f(v: Vec<isize>) -> (Vec<isize>, isize) {
    if let Some(&a) = v.get(0) {
        (v, a)
    } else {
        (v, 0)
    }
}

Playground


另请参阅:

答案 1 :(得分:0)

在第一个代码段中,键入Some(&a)时,您不会借用v,因为复制了a

在第二种情况下,Some(a)的类型为Option<&isize>,因此它包含对v的引用。当您尝试移动它时,它会触发错误。如果先复制它,然后返回该对,则它可以工作(但是您需要NLL feature):

#![feature(nll)]

fn main() {
    println!("{:?}", f(vec![1]))
}

fn f(v: Vec<isize>) -> (Vec<isize>, isize) {
    match v.get(0) {
        Some(a) => {
            let a = *a; // v is no more borrowed
            (v, a)
        },
        _ => (v, 0)
    }
}

Playground

借阅检查器并不完美,因此您经常会遇到一些稍微不一致的内容。