`&` 和 `ref` 有什么区别?

12

我了解&的工作原理,但它和ref之间有什么区别?它们可以互换使用吗?

我找到的唯一信息(因为在Google上搜索符号效果不佳)是来自Rust By Example的此页面,但它没有解释两者之间的区别。The Book 不是非常详细,而ref仅在模式章节中列出。但似乎ref也在该上下文之外使用。

那么,ref有哪些用途,与&有何差异?


非常相关,但并不完全是重复的,因为它不是关于ref&之间的比较:https://dev59.com/-Ibca4cB1Zd3GeqPa9a7 - Kroltan
1个回答

15

ref用于模式匹配中,将一个引用绑定到一个(可以取地址的值,或多或少)。

重要的是要理解模式与常规表达式相反,因为它们用于解构值。

这里有一个简单的例子。假设我们有以下内容:

let value = 42;

我们有两种方法可以将一个引用绑定到value:

let reference1 = &value;
let ref reference2 = value;
在第一个例子中,我们使用&作为运算符来获取value的地址。在第二个例子中,我们使用ref模式来“解构”lvalue。在两种情况下,变量的类型是&i32&也可以用于模式匹配,但它的作用相反:通过取消引用来解构引用。假设我们有:
let value = 42;
let reference = &value;

我们有两种方法可以取消引用reference

let deref1 = *reference;
let &deref2 = reference;

这里,deref1deref2 的类型均为 i32

然而,并非所有表达式都能像此处所示一样以两种方式编写。例如,您无法使用 & 来引用枚举变量中存储的值:您需要将其匹配。例如,如果要引用 Some 中的值的引用,则需要编写:

match option {
    Some(ref value) => { /* stuff */ }
    None => { /* stuff */ }
}

因为在Rust中,除了使用&操作符,没有其他访问该值的方法。


谢谢,所以像 fn blah(ref a: i32) {} 这样的定义与 fn blah(a: &i32) 是等价的,因为它们都可以表示相同的含义。 - Kroltan
5
不,它们不是等价的。函数参数中的模式(即 : 左侧的任何内容)纯粹是实现细节,调用方只能看到类型(即 : 右侧的内容)。第一种情况相当于 fn blah(tmp: i32) { let ref a = tmp; ... }。第一个函数被调用时使用 blah(0),而第二个函数被调用时使用 blah(&1)。当然,对于函数本身,a 的类型在两种情况下都是 &i32,只是外部接口不同。 - huon
@huon-dbaupp,这是否意味着ref变量会先复制/移动值? - Kroltan
2
fn blah(ref a: i32) -> {} 大致相当于 fn blah(temp_a: i32) { let ref a = temp_a; } - Eli Friedman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接