Rust’s ownership model is powerful, but sometimes you don’t want to take ownership of a value—you just want to look at it without moving it. That’s where borrowing with references comes in.
The Problem Without References #
Imagine you want to print a String from inside a function:
fn main() {
let name = String::from("Alice");
print_name(name); // ownership moves here
println!("{}", name); // ❌ ERROR: name was moved
}
fn print_name(s: String) {
println!("Name: {}", s);
}
Code language: Rust (rust)In this code:
- Passing
nameintoprint_nametransfers ownership. - After that,
nameis no longer valid inmain.
This is wasteful if we only want to read the value.
Enter References (&) #
Instead of transferring ownership, you can borrow the value with a reference:
fn main() {
let name = String::from("Alice");
print_name(&name); // pass a reference
println!("{}", name); // ✅ still works, ownership not moved
}
fn print_name(s: &String) {
println!("Name: {}", s);
}
Code language: Rust (rust)In this example:
&namemeans “borrownameinstead of moving it.”- The function receives a
&String, not the fullString. - Ownership stays with the caller (
main), sonameis still valid after the call.
References are Immutable by Default #
When you borrow with &, you cannot change the borrowed value:
fn main() {
let name = String::from("Alice");
print_name(&name);
// name is still valid and unchanged
println!("After function call: {}", name);
}
fn print_name(s: &String) {
// s.push_str(" Smith"); ❌ ERROR: cannot modify borrowed value
println!("Name: {}", s);
}
Code language: Rust (rust)Rust prevents modification because multiple parts of your code might be reading it at once, and allowing mutation would be unsafe.
Why Borrowing Is Safe #
Borrowing ensures:
- No unexpected copies → Rust avoids performance issues.
- No data races → You can have many immutable references at once, but not a mix of mutable and immutable ones.
- Memory safety → The owner controls when the value is dropped.
Example with Multiple References #
fn main() {
let text = String::from("Rust");
let r1 = &text;
let r2 = &text;
println!("r1: {}, r2: {}", r1, r2); // ✅ both work
// text is still valid here too
println!("Original: {}", text);
}
Code language: Rust (rust)Multiple immutable references (&) are fine because they only read, never change.
Summary #
- Ownership means one variable controls a value.
- Borrowing (
&) lets you read a value without taking ownership. - References are immutable by default → safe and efficient.
- You can have many immutable references at once.
Was this Helpful ?