Rust 例如:ref模式
我无法理解锈迹中的Rust 例如:ref模式,rust,Rust,我无法理解锈迹中的ref模式。我指的是 以下是我不理解的代码: let point = Point { x: 0, y: 0 }; let _copy_of_x = { // `ref_to_x` is a reference to the `x` field of `point` let Point { x: ref ref_to_x, y: _ } = point; // Return a copy of the `x` field of `point`
ref
模式。我指的是
以下是我不理解的代码:
let point = Point { x: 0, y: 0 };
let _copy_of_x = {
// `ref_to_x` is a reference to the `x` field of `point`
let Point { x: ref ref_to_x, y: _ } = point;
// Return a copy of the `x` field of `point`
*ref_to_x
};
我得到最后一个let
表达式(?)是某种模式匹配。所以我的理解是ref\u to_x
应该等于0
,原始点的x
值
但是我不明白ref
实际上做了什么。当我添加如下代码时:
println!("x: {}", point.x);
println!("ref_to_x: {}", ref_to_x);
println!("*ref_to_x: {}", *ref_to_x);
我总是得到0
,所以似乎没有什么区别。不知何故,我希望ref\u to\u x
有一个内存地址,而*ref\u to\u x
可能再次是解引用值
我可以用myx
替换ref-ref\u to\u x
和*ref\u to\u x
,代码仍然有效。有什么区别?ref
到底做什么
编辑:在阅读了dbaupp的答案并使用ref_to_x
和*ref_to_x
进行了一些添加之后,事情变得更清楚了;不能将整数添加到ref_to_x
,因为它是一个引用。我想我是被弄糊涂了,因为当你打印一个引用时,没有任何引用的指示。ref
在匹配的内存块中创建一个指针,在这种情况下,ref\u to\u x
直接指向存储point.x
的内存,在本例中,这与写入let ref_to_x=&point.x
相同
这种模式非常重要,因为它允许人们深入复杂的数据结构,而不会干扰所有权层次结构。例如,如果有val:&Option
,则写入
match *val {
Some(s) => println!("the string is {}", s),
None => println!("no string"
}
不合法,会出现如下错误:
<anon>:3:11: 3:15 error: cannot move out of borrowed content
<anon>:3 match *val {
^~~~
<anon>:4:14: 4:15 note: attempting to move value to here
<anon>:4 Some(s) => {}
^
<anon>:4:14: 4:15 help: to prevent the move, use `ref s` or `ref mut s` to capture value by reference
<anon>:4 Some(s) => {}
^
:3:11:3:15错误:无法移出借用的内容
:3匹配*val{
^~~~
:4:14:4:15注意:正在尝试将值移动到此处
:4部分=>{}
^
:4:14:4:15帮助:要防止移动,请使用'ref s'或'ref mut s'通过引用捕获值
:4部分=>{}
^
从借用的值中取得所有权(移动)是不合法的,因为这可能会损坏借用该值的对象(违反其不变量,导致数据意外消失等)
因此,我们可以使用一个引用,通过借用&
引用,只指向内存中的某个点
这里有一点微妙之处,因为(a)点
不是借来的,所以可以移出点
(这也会消耗点
的所有权,意味着除非重新初始化,否则以后不能使用它)和(b)类型int
是Copy
,因此在按值使用时不会移动所有权。这就是为什么使用myx
效果很好的原因。如果x
的类型是,比如说,String
(这不是Copy
)如果借用了点
,则需要参考
。使用参考
创建的参考与使用和获取的参考完全相同
不同之处在于语法中允许它们的位置。作业左侧的ref
类似于在右侧添加&
这些表达式是等效的:
let ref x1 = y;
let x2 = &y;
这种冗余的存在是因为模式匹配中的&
用于要求引用已经存在,而不是创建新引用:
let foo = 1;
match foo {
ref x => {
/* x == &1 */
match x {
&y => /* y == 1 */
}
},
}
()