在从引用中分配变量时,ref和&之间的区别是什么?

Ser*_*mov 5 syntax reference pattern-matching rust

这段代码有什么问题?

fn example() {
    let vec = vec![1, 2, 3];
    let &_y = &vec;
}
Run Code Online (Sandbox Code Playgroud)
error[E0507]: cannot move out of borrowed content
 --> src/lib.rs:3:15
  |
3 |     let &_y = &vec;
  |         ---   ^^^^ cannot move out of borrowed content
  |         ||
  |         |data moved here
  |         help: consider removing the `&`: `_y`
  |
note: move occurs because `_y` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
 --> src/lib.rs:3:10
  |
3 |     let &_y = &vec;
  |          ^^
Run Code Online (Sandbox Code Playgroud)

为什么这是正确的?

let vec = vec![1, 2, 3];
let ref _y = &vec;
Run Code Online (Sandbox Code Playgroud)

Mat*_* M. 8

模式绑定可以得到一些使用;)

为了理解编译器的功能,您可以使用该let _: () = ...;技巧.通过分配类型变量(),可以强制编译器打印一条错误消息,为您提供为变量推断的类型.


在第一个例子中:

let vec = vec![1, 2, 3];
let &y = &vec;
let _: () = y;
Run Code Online (Sandbox Code Playgroud)

我们得到:

error[E0308]: mismatched types
 --> src/lib.rs:4:13
  |
4 | let _: () = y;
  |             ^ expected (), found struct `std::vec::Vec`
  |
  = note: expected type `()`
             found type `std::vec::Vec<{integer}>`
Run Code Online (Sandbox Code Playgroud)

的类型yVec<i32>.

这意味着你是:

  1. 借入vec一个临时的
  2. 试图vec进入y,这是被禁止的,因为vec已经借来了.

等效的正确代码是:

let vec = vec![1, 2, 3];
let y = vec;
Run Code Online (Sandbox Code Playgroud)

在第二个例子中:

let vec = vec![1, 2, 3];
let ref y = &vec;
let _: () = y;
Run Code Online (Sandbox Code Playgroud)

我们得到:

error[E0308]: mismatched types
 --> src/lib.rs:4:17
  |
4 |     let _: () = y;
  |                 ^ expected (), found reference
  |
  = note: expected type `()`
             found type `&&std::vec::Vec<{integer}>`
Run Code Online (Sandbox Code Playgroud)

y就是这样&&Vec<i32>.

这让我们看到它let ref a = b;通常相当于let a = &b;,因此在这种情况下:let y = &&vec;.

ref是为了解构; 例如,如果你有:

let vec = Some(vec![1, 2, 3]);
if let Some(ref y) = vec {
    // use `y` here
}
Run Code Online (Sandbox Code Playgroud)

即使这里有类型,你也可以ref在这里使用y,&Vec<i32> 无需移动即可绑定.实际上,目的是在解构期间在现有对象内部引用.vecOption<Vec<i32>>ref

一般而言,在let声明中,您不会使用ref.

而自Rust 1.26以来,ref推断出模式匹配; 看到匹配人体工程学稳定性.


Pao*_*lla 5

&当在装订的右端和左端使用相同的符号 ( ) 时,会执行两种不同的操作。左侧的工作方式类似于模式匹配,因此:

let x = (y, z); // x contains a tuple with value (y, z)
let (a, b) = x  // x is destructured into (a, b), so now
                // a has value y and b has value z
Run Code Online (Sandbox Code Playgroud)

同样的方式

let x = &y; // x is a reference to y
let &z = x; // this is like let &z= &y, so we want z to be y
            // this is equivalent to let z = *x
Run Code Online (Sandbox Code Playgroud)

ref左侧的绑定表示“通过引用而不是通过值进行模式匹配” 。所以这两个语句是等价的:

let ref y = vec;
let y = &vec;
Run Code Online (Sandbox Code Playgroud)

尽管在let中,第二个更惯用。

您可以在有关 rust 的指针/参考章节中通过示例查看更多示例