Understand Ownership and borrowing in Rust
Tags: rust, programming, beginners, tutorial
Published: 2023-08-21 06:08:23




There are many tutorials available on this topic, here I try to show you how I understand this simple but very important concept

```rust
fn main() {
    let mut num = 42;

    // Immutable Borrow
    let borrowed_immutable = &num;
    println!("Immutable Borrow: {}", borrowed_immutable);

    // Mutable Borrow
    let borrowed_mutable = &mut num;
    *borrowed_mutable += 10;
    println!("Mutable Borrow: {}", borrowed_mutable);

    // Cannot do an immutable borrow while there's a mutable borrow
    // println!("Immutable Borrow: {}", borrowed_immutable);
}
```

The main function starts by creating a mutable variable `num` with a value of `42`.

### Immutable Borrowing:

An immutable borrow is created with `let borrowed_immutable = &num;`. This means we're borrowing num in an immutable way, so we can read its value but not modify it.

We can have multiple such shared refereces.


### Mutable Borrowing:
A mutable borrow is created with `let borrowed_mutable = &mut num;`. This allows us to modify the value of num through the borrowed reference.

Since it's a mutable borrow, we use the `*` operator to dereference the borrowed reference and modify the value. We add `10` to it.

The modified borrowed value is printed with `println!`.

### Trying to create an Immutable Borrow again

The code that attempts to create an immutable borrow after a mutable borrow is commented out.

Rust does not allow an immutable borrow while there's a mutable borrow. This is to prevent potential data races.

In Rust, mutable and immutable borrows have different rules to ensure memory safety.

When you have a mutable borrow, no other borrow (mutable or immutable) can be active at the same time.

This prevents data races where multiple parts of your code try to change data concurrently, which can lead to unpredictable behavior.

## Understanding Ownership
```rust
fn main() {
    let num: Box<i32> = Box::new(33);
    
    ownership(num);
    
    // println!("after owner: {}", num);
}

fn ownership(num: Box<i32>) {
    println!("owned: {}", num);
    
    let num2 = *num.as_ref() * 2;
    
    println!("new num: {}", num2);
}
```

### In the main function:

A variable named `num` is created and assigned a `Box` that contains the value `33`.

The `Box` is a smart pointer created on heap that helps manage memory allocation and deallocation.

The ownership function is called, passing the `num` Box to it.

There's a commented-out line that attempts to print the value of num after it's been passed to the ownership function. 

However, this line is commented out because Rust's ownership system prevents using num after it's been moved to the ownership function.

The ownership function receives the ownership of the `num` Box.

The value inside the `Box` is printed using `println!`.

The value is then multiplied by `2` and assigned to the variable `num2`.

The new value, `num2`, is printed using `println!`.

## The Key Concept

The key concept here is Rust's ownership system, which ensures memory safety and prevents certain types of bugs like null pointer dereferencing and data races.

In Rust, when a value is passed into a function (or moved to another variable), the ownership of that value is transferred. 

This means the original variable can't be used afterward, to prevent issues like double freeing memory or using invalid references.

The Box type is used here to allocate memory on the heap for the `i32` value (instead of the stack).

When the `Box` is passed to the ownership function, ownership of the data moves to the function.

> This concept is called "moving" in Rust.

This is the rust default as compared to CPP where values are copied.

## Video Format

If you prefer video format, then have a look at this short

> https://www.youtube.com/shorts/AbsYKCEd-XU

## Conclusion
This code demonstrates Rust's strict ownership model and how it helps prevent memory-related bugs.

It might look a bit complicated at first, but Rust's ownership and borrowing rules play a significant role in ensuring the safety and reliability of your programs.

## Claps Please!
If you found this article helpful I would appreciate some claps 👏👏👏👏, it motivates me to write more such useful articles in the future.

Follow for regular awesome content and insights.

## Subscribe to my Youtube channel

Subscribe to my youtube channel if you are on the lookout for more such awesome content in video format.

> https://www.youtube.com/@dsysd-dev

## Follow me on twitter 🐥

Join me on Twitter for a daily dose of knowledge, fascinating trivia, and valuable insights. Let's embark on a journey of continuous learning and discovery together! Follow me to stay inspired and informed. 🚀

> https://twitter.com/dsysd_dev

## Subscribe to my Newsletter

If you like my content, then consider subscribing to my free newsletter, to get exclusive, educational, technical, interesting and career related content directly delivered to your inbox

> https://dsysd.beehiiv.com/subscribe

## Important Links

Thanks for reading the post, be sure to follow the links below for even more awesome content in the future.
Twitter: https://twitter.com/dsysd_dev
Youtube: https://www.youtube.com/@dsysd-dev
Github: https://github.com/dsysd-dev
Medium: https://medium.com/@dsysd-dev
Email: dsysd.mail@gmail.com
Telegram 📚: https://t.me/dsysd_dev_channel
Linkedin: https://www.linkedin.com/in/dsysd-dev/
Newsletter: https://dsysd.beehiiv.com/subscribe
Gumroad: https://dsysd.gumroad.com/
Dev.to: https://dev.to/dsysd_dev/