Rustlers Atom 2.3: Mutable and immutable borrow
On this page
<figure class="video" style="margin:0;">
<div style="position:relative;width:100%;padding-bottom:56.25%;height:0;overflow:hidden;">
<iframe src="https://www.youtube.com/embed/14ZB8dgd08?si=JuoLg594n1nlAuL"
title="YouTube video player"
style="position:absolute;top:0;left:0;width:100%;height:100%;border:0;"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
referrerpolicy="strict-origin-when-cross-origin"
allowfullscreen></iframe>
</div>
</figure>
Owning values is great, but moving them around constantly is stupid. Often, you want to let a function use a value without taking responsibility for freeing it. In Rust, this is called borrowing. You borrow a value by creating a reference. References are pointers that are guaranteed to be valid and align with Rust’s safety rules. There are two types.
Immutable Reference &T#
An immutable reference allows you to read data but not change it. You create one by adding & before the variable.
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1); // Pass a reference
println!("The length of '{}' is {}.", s1, len); // s1 is still valid here
}
fn calculate_length(s: &String) -> usize {
s.len()
} // s goes out of scope, but nothing happens because s didn't own the dataYou can have as many immutable references to a value as you like, simultaneously. It’s like a read-only Google Doc: everyone can look, but nobody can type.
Mutable Reference &mut T#
If you want a function to modify the borrowed value, you use a mutable reference. You create it with &mut. To create a &mut reference, the owner variable must also be declared as mut.
fn main() {
let mut s = String::from("hello");
change(&mut s);
println!("{}", s); // "hello, world"
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}Dereferencing#
Under the hood, references are pointers. To access the data they point to, you technically need to dereference them using *. However, Rust has a feature called auto-dereferencing for method calls and field access.
let x = 5;
let y = &mut x;
*y += 1; // Explicit dereference needed to change the integer valueFor most dot-methods (s.len(), v.push()), Rust handles the pointer logic for you automatically.