Shared References
Moving ownership everywhere gets tedious. What if you just want to look at a value without taking it?
In Python, everything is passed by reference automatically:
def print_length(items):
print(len(items)) # just reads, doesn't modify
names = ["Alice", "Bob"]
print_length(names)
print(names) # still valid
In Rust, you borrow with &:
fn print_length(items: &Vec<String>) {
println!("{}", items.len());
}
let names = vec!["Alice".to_string(), "Bob".to_string()];
print_length(&names); // lend with &
println!("{:?}", names); // still ours
The borrowing rules
A shared reference (&T) is read-only. You can have as many as you want:
let text = String::from("hello");
let r1 = &text;
let r2 = &text;
let r3 = &text;
println!("{} {} {}", r1, r2, r3); // all valid
But you cannot modify through a shared reference:
fn try_modify(s: &String) {
// s.push_str(" world"); // ERROR: cannot borrow as mutable
}
Why this matters
Shared references guarantee that the data won't change while you're reading it. In Python, another thread could modify a list while you're iterating — leading to subtle bugs. Rust prevents this at compile time.
Dereferencing
Sometimes you need to access the value behind a reference:
let x = 5;
let r = &x;
assert_eq!(*r, 5); // *r dereferences to get the value
For method calls, Rust auto-dereferences, so r.to_string() works without (*r).to_string().
Login to see the full task and start coding.
Topics
This is a premium exercise
Log in to unlock the full exercise and start coding.
Login to access this exercise