Rust does not have garbage collection. Instead, it has ownership rules to manage memory automatically.
fn main() {
let banana = String::from("banana"); // banana owns this String
let monkey = banana; // Ownership MOVED to monkey!
// println!("{}", banana); // ERROR! banana lost ownership!
println!("{}", monkey); // Works!
}
When banana gives ownership to monkey, it loses access to the value.
fn main() {
{
let food = String::from("apple"); // food is created
println!("Monkey eats: {}", food);
} // food goes out of scope, and is DROPPED
// println!("{}", food); // ERROR! food is gone!
}
When food goes out of scope, Rust automatically cleans it up.
Rust allows borrowing instead of moving ownership.
fn eat(banana: &String) { // Borrowing (not moving)
println!("Monkey eats: {}", banana);
}
fn main() {
let banana = String::from("banana");
eat(&banana); // Works! banana is still owned by main
println!("Banana is still here: {}", banana);
}
Borrowing (&) allows you to use a value without owning it.
You can:
fn main() {
let mut banana = String::from("banana");
let monkey1 = &banana; // Immutable borrow
let monkey2 = &banana; // Another immutable borrow
println!("Monkeys see: {} and {}", monkey1, monkey2); // Works!
// let monkey3 = &mut banana; // ERROR! Can't mutate while others read!
}
fn main() {
let mut banana = String::from("banana");
let monkey = &mut banana; // Allowed, only ONE mutable borrow
monkey.push_str(" banana"); // Modify banana!
println!("Monkey added more bananas: {}", monkey);
}
Rust checks lifetimes to make sure values don’t disappear while being borrowed.
fn longest<'a>(s1: &'a str, s2: &'a str) -> &'a str {
if s1.len() > s2.len() { s1 } else { s2 }
}
fn main() {
let banana = String::from("banana banana banana");
let apple = String::from("apple");
let best = longest(&banana, &apple);
println!("Best fruit: {}", best);
}
Here, longest<’a> means both inputs and output share the same lifetime.
fn bad() -> &String { // ERROR! No lifetime!
let banana = String::from("banana");
&banana // banana is dropped here!
}
The value disappears before it can be returned.