Mastering Rust: Ownership, Borrowing, and Lifetimes.
Course Title: Mastering Rust: From Basics to Systems Programming
Section Title: Ownership, Borrowing, and Lifetimes
Topic: Write Rust programs that demonstrate ownership and borrowing concepts. (Lab topic)
In this lab, we'll put the concepts of ownership and borrowing into practice by writing Rust programs that demonstrate these concepts. We'll explore different scenarios and exercises to reinforce your understanding of ownership and borrowing rules in Rust.
Exercise 1: Ownership and Borrowing Basics
Create a new Rust project using Cargo by running the command cargo new ownership_borrowing
in your terminal. Update the main.rs
file with the following code:
fn main() {
let s = String::from("Hello, World!"); // s owns the string "Hello, World!"
println!("{}", s); // prints "Hello, World!"
let len = calculate_length(&s); // len borrows s
println!("{}", len); // prints the length of the string "Hello, World!"
}
fn calculate_length(s: &String) -> usize {
s.len()
}
In this example, we define a string s
that owns the string "Hello, World!". We then pass a reference to s
to the calculate_length
function, which returns the length of the string. The &s
syntax creates a reference to s
, allowing the calculate_length
function to borrow s
without taking ownership of it.
Exercise 2: Mutable References
Update the main.rs
file with the following code:
fn main() {
let mut s = String::from("Hello, World!"); // s owns the string "Hello, World!"
println!("{}", s); // prints "Hello, World!"
let len = calculate_length(&s); // len borrows s
println!("{}", len); // prints the length of the string "Hello, World!"
let result = append_str(&mut s); // result borrows mutably s
println!("{}", result); // prints "Append success"
println!("{}", s); // prints the updated string
}
fn calculate_length(s: &String) -> usize {
s.len()
}
fn append_str(s: &mut String) -> &str {
s.push_str(" Appended");
"Append success"
}
In this example, we define a mutable string s
that owns the string "Hello, World!". We then pass a mutable reference to s
to the append_str
function, which appends a string to s
. The &mut s
syntax creates a mutable reference to s
, allowing the append_str
function to borrow s
mutably.
Exercise 3: Aliasing
Update the main.rs
file with the following code:
fn main() {
let mut s = String::from("Hello, World!"); // s owns the string "Hello, World!"
println!("{}", s); // prints "Hello, World!"
let len = calculate_length(&s); // len borrows s
println!("{}", len); // prints the length of the string "Hello, World!"
{
let r1 = &s; // r1 borrows s
println!("{}", r1); // prints "Hello, World!"
// let r2 = &s; // error: cannot borrow as mutable
}
let r2 = &mut s; // r2 borrows mutably s
println!("{}", r2); // prints "Hello, World!"
}
In this example, we define a mutable string s
that owns the string "Hello, World!". We then define two references r1
and r2
that borrow s
. However, we can't define r2
while r1
is still in scope, because r2
borrows s
mutably and r1
borrows s
immutably.
Practical Takeaways
- Ownership and borrowing rules ensure memory safety in Rust programs.
- Use references to borrow values without taking ownership of them.
- Use mutable references to borrower values mutably.
- Be careful when borrowing values to avoid aliasing issues.
External Resources
Comments and Questions
If you have any questions or need help with the exercises, feel free to leave a comment below.
Next topic: Conditional statements: if, else, match. (From: Control Flow and Functions)
Images

Comments