此代码有什么问题?
fn example() {
let vec = vec![1, 2, 3];
let &_y = &vec;
}
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;
| ^^
为什么这是正确的?
let vec = vec![1, 2, 3];
let ref _y = &vec;
答案 0 :(得分:8)
模式绑定可以使用;)
为了理解编译器的功能,您可以使用let _: () = ...;
技巧。通过分配类型为()
的变量,可以强制编译器打印一条错误消息,为您提供为变量推断的类型。
在第一个例子中:
let vec = vec![1, 2, 3];
let &y = &vec;
let _: () = y;
我们得到:
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}>`
y
的类型为Vec<i32>
。
这意味着你是:
vec
暂时vec
移至y
,因为vec
已被借用而被禁止。等效的正确代码是:
let vec = vec![1, 2, 3];
let y = vec;
在第二个例子中:
let vec = vec![1, 2, 3];
let ref y = &vec;
let _: () = y;
我们得到:
error[E0308]: mismatched types --> src/lib.rs:4:17 | 4 | let _: () = y; | ^ expected (), found reference | = note: expected type `()` found type `&&std::vec::Vec<{integer}>`
因此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
}
您可以在ref
使用y
将<{1}}绑定到&Vec<i32>
而不移动,即使vec
此处的类型为{{1} }}。实际上,Option<Vec<i32>>
的目的是在解构期间在内部引用。
通常,在ref
语句中,您不会使用let
。
自Rust 1.26起,ref
在模式匹配中得到推断;请参阅stabilization of match ergonomics。
答案 1 :(得分:2)
当在绑定的右端和左端使用时,相同的符号(&
)正在做两件事。左侧的工作方式类似于模式匹配,所以:
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
以同样的方式
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
左侧的ref
绑定表示&#34;模式匹配参考,而不是值&#34;。所以这两个陈述是等价的:
let ref y = vec;
let y = &vec;
虽然在一个让,第二个是更惯用。
上看到更多示例答案 2 :(得分:1)
首先,您的工作示例中不需要&
。如果您使用它,最终会得到&&Vec<_>
,这是您真正不需要的。
let vec = vec![1, 2, 3];
let ref y = vec;
您的第一个代码的问题是您一次做两件事。让我们把它分成两部分:
第一部分创建对vec
let y1 = &vec;
第二部分(变量绑定前的&
),destructures。
let &y2 = y1;
这意味着您正在尝试移出引用,该引用仅在类型为Copy
时有效,因为任何移动尝试都将复制该对象。