Ownership and Borrowing in Rust

Introduction

Welcome to this lesson on Ownership and Borrowing in Rust. In previous lessons, we've established a strong foundation in core Rust concepts like structs, enums, generics and traits. Now, we'll delve into Rust's unique approach to memory safety: Ownership and Borrowing. Understanding these concepts is crucial as they form the backbone of safe and efficient programming in Rust, allowing you to write robust applications with confidence.

Memory Management in Rust

Before we dive in, let's briefly discuss how Rust manages memory using the stack and the heap:

  • Stack: Used for storing data with a known, fixed size at compile time. It's fast for allocation and deallocation.
  • Heap: Used for data that can change size or when the size is not known at compile time, like String. It requires explicit memory management.

Ownership rules in Rust govern how heap-allocated data is managed, preventing issues like dangling pointers and data races at compile time.

Exploring Ownership in Rust

Ownership in Rust is a set of rules governing how a program manages memory. These rules ensure clean memory usage and prevent issues like dangling references. There are three main rules of ownership:

  1. Each value in Rust has a variable that's its owner.
  2. There can only be one owner at a time.
  3. When the owner goes out of scope, the value is dropped.

Consider the following function that takes ownership of a String:

fn takes_ownership(some_string: String) {
    println!("Owned string: {}", some_string);
}

In this code:

  • some_string takes ownership of the String parameter passed to it.
  • The ownership moves to some_string, and when it goes out of scope at the end of the function, the String is dropped.

For instance:

fn main() {
    let s = String::from("Hello");
    takes_ownership(s);
    // 's' is no longer valid here as ownership has been transferred
    // println!("{}", s); // This would cause a compile-time error
}

When takes_ownership is called, s is moved into the function and dropped when it leaves the scope. Attempting to use s after it has been moved results in a compile-time error, ensuring memory safety by preventing access to dropped data.

Copy vs Move Semantics

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal