References in Rust
In this lesson, you will learn about references in Rust. References allow you to access data without taking ownership of it.
References are closely related to ownership and borrowing and play a critical role in Rust’s memory safety model.
What Is a Reference?
A reference is a way to refer to a value without owning it. Instead of moving data, Rust allows you to borrow it using references.
References are created using the & symbol.
Creating References
You can create a reference to a variable by prefixing it with &.
let name = String::from("Rust");
let ref_name = &name;
println!("{}", ref_name);
Here, ref_name borrows the value owned by name.
References and Ownership
Creating a reference does not transfer ownership. The original owner remains responsible for the data.
This allows safe reuse of values without copying or moving them.
Immutable References
By default, references are immutable. You can read data through them, but you cannot modify it.
fn display(s: &String) {
println!("{}", s);
}
fn main() {
let text = String::from("Dataplexa");
display(&text);
}
The value text remains unchanged after the function call.
Mutable References
Mutable references allow you to modify the value they point to.
To create a mutable reference, both the variable and the reference must be declared as mutable.
fn change(s: &mut String) {
s.push_str(" Language");
}
fn main() {
let mut lang = String::from("Rust");
change(&mut lang);
println!("{}", lang);
}
Rules for References
Rust enforces strict rules for references:
- You can have multiple immutable references
- You can have only one mutable reference at a time
- You cannot have mutable and immutable references together
Dangling References
A dangling reference is a reference to data that no longer exists. Rust prevents dangling references at compile time.
// This code will not compile
fn create_ref() -> &String {
let s = String::from("Rust");
&s
}
Rust does not allow returning references to local variables that go out of scope.
References and Scope
References are valid only within the scope they are used. Once the reference goes out of scope, the value can be borrowed again.
let mut s = String::from("Hello");
{
let r = &s;
println!("{}", r);
}
let r2 = &mut s;
r2.push_str(" Rust");
Why References Matter
References make Rust:
- Memory safe
- Efficient
- Free from data races
- Predictable at compile time
📝 Practice Exercises
Exercise 1
Create an immutable reference and print its value.
Exercise 2
Create a mutable reference and update a string.
Exercise 3
Try returning a reference to a local variable and observe the error.
Exercise 4
Demonstrate reference scope behavior.
✅ Practice Answers
Answer 1
let value = String::from("Rust");
let r = &value;
println!("{}", r);
Answer 2
let mut s = String::from("Hello");
let r = &mut s;
r.push_str("!");
Answer 3
// Rust prevents dangling references
Answer 4
{
let r = &value;
println!("{}", r);
}
What’s Next?
Now that you understand references, the next lesson will introduce slices, which allow you to reference parts of data safely.