CUSTOMISED
Expert-led training for your team
Dismiss
Understanding Rust Ownership and Borrowing

6 April 2023

Understanding Rust Ownership and Borrowing

Introduction: Rust is a programming language designed with a focus on safety, performance, and reliability. One of the key features that sets Rust apart from other programming languages is its ownership and borrowing system. This system ensures that only one piece of code can modify a given piece of data at any given time, preventing common bugs such as data races and null pointer exceptions.

In this guide, we will take a closer look at Rust's ownership and borrowing system. We will explore how it works, why it is important, and how to use it effectively in your Rust programs. We will provide code examples throughout the guide to illustrate the concepts.

Rust Official Documentation: Before diving into the topic, it's important to have a good understanding of the official Rust documentation on Ownership and Borrowing. Here are the links to the Rust official documentation:

Understanding Ownership: In Rust, every value has an owner, which is responsible for managing the memory used by the value. When a value is created, the owner is the variable that holds the value. When the owner goes out of scope, Rust will automatically free the memory used by the value.

For example, consider the following code:

let x = 5; // x is the owner of the value 5

In this case, the variable x is the owner of the integer value 5. When x goes out of scope, Rust will automatically free the memory used by 5.

Transferring Ownership: Ownership can be transferred from one variable to another using the move keyword. This is often used when passing values as function arguments or returning values from functions.

For example, consider the following code:

fn main() { let x = String::from("hello"); // x is the owner of the string let y = x; // ownership of the string is transferred to y println!("{}", y); // prints "hello" }

In this case, the variable x is the owner of the String value "hello". When y is assigned the value of x, ownership of the String is transferred to y. When x goes out of scope, Rust will not free the memory used by the String because ownership has been transferred to y.

Borrowing: Borrowing is a mechanism in Rust that allows a piece of code to borrow a reference to a value without taking ownership of it. This is useful when you want to use a value without modifying it, or when you want to pass a value to a function without transferring ownership.

In Rust, we can borrow references using the & symbol. There are two types of references in Rust: immutable references (&T) and mutable references (&mut T).

For example, consider the following code:


 

rust

fn print_value(x: &i32) { println!("{}", x); } fn main() { let x = 5; print_value(&x); // pass a reference to x without transferring ownership }

In this case, the print_value function takes an immutable reference to an i32 value. When we call the function with print_value(&x), we are passing a reference to `x without transferring ownership of the value. This allows us to use the value in the function without changing it.

Mutable Borrowing: In Rust, mutable borrowing is used when you want to modify the value being borrowed. This is done using a mutable reference (&mut T).

For example, consider the following code:

fn add_one(x: &mut i32) { *x += 1; } fn main() { let mut x = 5; add_one(&mut x); // pass a mutable reference to x println!("{}", x); // prints "6" }

In this case, the add_one function takes a mutable reference to an i32 value. When we call the function with add_one(&mut x), we are passing a mutable reference to x. This allows us to modify the value of x inside the function using the dereferencing operator *.

Dangling References: One of the most common errors in Rust is a dangling reference. This occurs when a reference is used after the value it refers to has been freed. Rust prevents this by ensuring that references always point to valid memory.

For example, consider the following code:

fn main() { let x = String::from("hello"); let y = &x; drop(x); // free the memory used by x println!("{}", y); }

In this case, the variable y is a reference to the String value "hello". When we call drop(x), Rust frees the memory used by x. This means that y now points to invalid memory, causing a runtime error when we try to print it.

Conclusion: In this guide, we have explored Rust's ownership and borrowing system. We have seen how it works, why it is important, and how to use it effectively in your Rust programs. We have provided code examples throughout the guide to illustrate the concepts.

Rust's ownership and borrowing system can take some time to get used to, but it is an important feature of the language that can help you write more reliable and performant code. By understanding how ownership and borrowing work in Rust, you will be well on your way to becoming a proficient Rust programmer.

References:

About the author: Daniel West
Tech Blogger & Researcher for JBI Training

CONTACT
+44 (0)20 8446 7555

[email protected]

SHARE

 

Copyright © 2024 JBI Training. All Rights Reserved.
JB International Training Ltd  -  Company Registration Number: 08458005
Registered Address: Wohl Enterprise Hub, 2B Redbourne Avenue, London, N3 2BS

Modern Slavery Statement & Corporate Policies | Terms & Conditions | Contact Us

POPULAR

Rust training course                                                                          React training course

Threat modelling training course   Python for data analysts training course

Power BI training course                                   Machine Learning training course

Spring Boot Microservices training course              Terraform training course

Kubernetes training course                                                            C++ training course

Power Automate training course                               Clean Code training course