Ownership and Borrowing in Rust
Ownership is a key concept in Rust that ensures memory safety. Each value in Rust has a variable that owns it, and there can only be one owner at a time. Borrowing allows you to reference a value without taking ownership.
Ownership Rules
Rust's ownership rules are as follows:
- Each value in Rust has a variable that owns it.
- There can only be one owner at a time.
- When the owner goes out of scope, the value is dropped.
Example: Ownership Transfer
fn main() {
let s1 = String::from("hello");
let s2 = s1; // Ownership of the string is transferred to s2
// println!("{}", s1); // This would cause a compile-time error
println!("{}", s2); // s2 is now the owner
}
Borrowing and References
Borrowing allows you to reference a value without taking ownership. You can have either one mutable reference or multiple immutable references at a time.
fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1); // Pass a reference to s1
println!("Length of '{}' is {}.", s1, len);
let mut s2 = String::from("world");
change_string(&mut s2); // Pass a mutable reference to s2
println!("Changed string: {}", s2);
}
fn calculate_length(s: &String) -> usize {
s.len()
}
fn change_string(s: &mut String) {
s.push_str("!");
}
Slices
Slices allow you to reference a contiguous sequence of elements in a collection.
fn main() {
let s = String::from("hello world");
let hello = &s[0..5]; // Slice from index 0 to 5
let world = &s[6..11]; // Slice from index 6 to 11
println!("{} {}", hello, world);
}
Lifetime Annotations
Lifetimes ensure that references are valid for as long as they are used. Rust's borrow checker enforces these rules at compile time.
fn main() {
let string1 = String::from("long string is long");
let string2 = String::from("xyz");
let result = longest(string1.as_str(), string2.as_str());
println!("The longest string is {}", result);
}
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() {
x
} else {
y
}
}
Interactive Code Examples
Try running these examples in your Rust environment to see how they work!
// Interactive Example
fn main() {
let s1 = String::from("hello");
let s2 = s1; // Ownership is transferred to s2
println!("{}", s2);
}
Practice Problems
Test your understanding with these practice problems:
- Write a Rust function that takes a string slice and returns the first word.
- Write a Rust program that demonstrates the difference between mutable and immutable references.
- Write a Rust function that takes two string slices and returns the longer one.