A reference of a variable is a pointer that leads to that variable. Rust uses the concept of ownership, which is associated with how references are used.
An ampersand (&
) is used with a variable’s name while passing its reference instead of its value to a function. The function’s signature should also have an ampersand with the type of argument that receives the reference. When a function takes in a reference as a parameter, it is called borrowing.
// Passing a reference of 'x':
foo(&x);
// foo borrows the value of 'x':
fn foo(a: &i32) {
// Do something
}
There are two types of references in Rust:
A reference is immutable by default. Similar to an immutable variable, an immutable reference variable cannot change the value of anything it refers to. For example, in the code below, the function foo()
is not allowed to change the value of the title
string after borrowing it:
let title = String::from("hello");
foo(&title);
fn foo(ptr: &String) {
// Error while modifying 'title':
ptr.push_str(", world");
}
If the mut
keyword is used with the &
symbol, we can modify a borrowed value:
The variable itself also has to be mutable for it to be changed after it has been borrowed.
fn main() {let mut x = 10;println!("x = {}", x);// Pass 'x' as a mutable reference:change_value(&mut x);// Print new value of 'x':println!("New value of x = {}", x);}fn change_value(s: &mut i8) {// Dereferencing 's' and changing its value:*s = 5;}
let ref1 = &mut x;
let ref2 = &mut x;
x
simultaneously.let ref1 = &x;
let ref2 = &mut x;
// Pass immutable ref1 to read():
read(ref1);
fn read(i: &i8) {
// Use value of 'x' using immutable reference 'i'
}
ref1
ends at line 5, i.e., before the mutable ref2
was created.fn main() {let mut x = 10;let ref1 = &x;read_value(ref1); // Lifetime of ref1 ends herelet ref2 = &mut x;change_value(ref2);// Print new value of 'x':println!("New value of x = {}", *ref2);}fn read_value(i: &i8) {// Use immutable reference 'i':println!("x = {}", *i);}fn change_value(i: &mut i8) {// Use mutable reference 'i':*i = 5;}