G2Labs Grzegorz Grzęda
Ownership and borrowing in Rust
January 20, 2024
Deep Dive Into Ownership and Borrowing
Ownership
Fundamental Concept: Ownership is a set of rules that the Rust compiler checks at compile time. It’s not present in C, and understanding this is key to mastering Rust.
Rules of Ownership:
- Each value in Rust has a variable that’s called its owner.
- There can only be one owner at a time.
- When the owner goes out of scope, the value will be dropped.
Memory Management: Ownership is Rust’s way of managing memory. Unlike C, where you explicitly allocate and free memory, Rust automatically cleans up when an owner goes out of scope.
Ownership and Functions: Passing a variable to a function will transfer its ownership. If you want to use a variable after passing it to a function, you can pass a reference instead.
Borrowing
References: Instead of taking ownership, functions can borrow values using references. This is a fundamental part of Rust’s memory safety guarantees.
Immutable and Mutable References:
Immutable References (
&T
): Allow you to read data without taking ownership. You can have multiple immutable references.Mutable References (
&mut T
): Allow you to modify data. You can only have one mutable reference to a particular piece of data in a particular scope.
Rules of Borrowing:
- You can’t have a mutable reference while you have an immutable one.
- References must always be valid.
Lifetimes
Preventing Dangling References: Lifetimes are Rust’s way of ensuring that references don’t outlive the data they point to.
Explicit Lifetimes: In cases where the lifetime is not clear, you need to annotate lifetimes. This is a concept that doesn’t exist in C and is unique to Rust’s memory safety guarantees.
Lifetime Elision Rules: In many cases, the compiler can infer lifetimes, so explicit annotations are not needed.
Transition Tips for C Developers
- Understand, Don’t Memorize: Initially, ownership and lifetimes might seem restrictive, especially coming from C’s manual memory management. It’s crucial to understand the reasoning behind these rules for memory safety.
- Practice with Examples: Experiment with code snippets that demonstrate ownership, borrowing, and lifetimes. See how the compiler reacts to different scenarios.
- Compiler Messages: Rust’s compiler provides helpful messages. Use them to understand why certain codes might lead to errors regarding ownership or lifetimes.
These concepts form the backbone of Rust’s approach to memory safety and efficient resource management. While they represent a shift from C’s manual memory management, they offer a powerful toolset for writing safe and efficient code.