Skip to main content
  1. About
  2. For Teams
Asked
Modified 10 years ago
Viewed 1k times
13

I understand how & works, but what is the difference between that and ref? Are they interchangeable?

The only information I found (because searching for symbols on Google doesn't work very well) is this page on Rust By Example, but it doesn't explain the difference between the two. The Book is not very informative, and ref is only listed on the Patterns chapter. But it seems that ref is used outside that context too.

So, what are the uses of ref, and what's the difference to &?

1

1 Answer 1

18

ref is used in patterns to bind a reference to an lvalue (an lvalue is a value you can take the address of, more or less).

It's important to understand that patterns go "backwards" from normal expressions, since they're used to deconstruct values.

Here's a simple example. Suppose we have this:

let value = 42;

We can bind a reference to value in two ways:

let reference1 = &value;
let ref reference2 = value;

In the first case, we use & as an operator to take the address of value. In the second case, we use the ref pattern to "deconstruct" an lvalue. In both cases, the type of the variable is &i32.

& can also be used in patterns, but it does the opposite: it deconstructs a reference by dereferencing it. Suppose we have:

let value = 42;
let reference = &value;

We can dereference reference in two ways:

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

Here, the type of both deref1 and deref2 is i32.

It's not always possible to write the same expression in two ways as shown here, however. For example, you cannot use & to take a reference to a value stored in an enum variant: you need to match on it. For example, if you want to take a reference to the value in a Some, you need to write:

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

since there's no way in Rust you can use the & operator to access the value otherwise.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, so definitions like fn blah(ref a: i32) {} are equivalent to fn blah(a: &i32), when they can both be expressed?
@Kroltan No, they're not equivalent. A pattern (i.e. anything to the left of the :) in a function argument is purely an implementation detail, callers only see the types (i.e. things to the right of the :). The first case is equivalent to fn blah(tmp: i32) { let ref a = tmp; ... }. The first one is called like blah(0) while the second is called like blah(&1). Of course, the function itself, the type of a is &i32 in both case, it's just the external interface that differs.
@huon-dbaupp, does that mean that the ref variant will copy/move the value first?
fn blah(ref a: i32) -> {} is roughly equivalent to fn blah(temp_a: i32) { let ref a = temp_a; }.

Your Answer

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.

Morty Proxy This is a proxified and sanitized view of the page, visit original site.