我应该在哪里使用&v:&V描述函数签名中的参数?

时间:2019-06-17 14:52:19

标签: rust

您可以在Rust playground上找到以下代码。

fn main() {
    #[derive(Clone, Copy, Debug)]
    struct Foo {
        bar: u32,
    }

    fn take_ref(&f: &Foo) {
        println!("{:?}", f);
    }

    fn take_foo(f: Foo) {
        println!("{:?}", f);
    }

    let f = Foo {
        bar: 1,
    };

    take_ref(&f);
    println!("{:?}", f);

    take_foo(f.clone());
    println!("{:?}", f);
}

take_reftake_foo这些功能是否相同? 什么时候应该使用&v:&V而不是v:V?

1 个答案:

答案 0 :(得分:0)

通常,我认为您永远不应使用&f: &Foo格式。编译器接受它的唯一原因是因为函数参数(例如let赋值)实际上是不可辩驳的模式。如果您尝试放置常规模式,则可以在错误消息中看到这一点:

fn take_option (Some (f): Option<Foo>) {
    println!("{:?}", f);
}

不抱怨语法无效,而是给出以下错误消息:

error[E0005]: refutable pattern in function argument: `None` not covered
  --> src/main.rs:15:21
   |
15 |     fn take_option (Some (f): Option<Foo>) {
   |                     ^^^^^^^^ pattern `None` not covered

使用模式作为函数参数可以实现诸如自动元组,数组或结构分解之类的好功能:

fn take_tuple ((x, y): (i32, i32)) {
    println!("x: {}, y: {}", x, y);
}

fn take_array ([x, y]: [i32; 2]) {
    println!("x: {}, y: {}", x, y);
}

fn take_foo (Foo { bar: bar }: Foo) {
    println!("bar: {}", bar);
}

population
   .iter()
   .enumerate()
   .map (|(rank, person)| { ... });