Skip to content

Latest commit

 

History

History
102 lines (80 loc) · 5.17 KB

File metadata and controls

102 lines (80 loc) · 5.17 KB

What is Ownership?

Ownership is a set of rules that govern how a Rust program manages memory. All programs have to manage the way they use a computer’s memory while running. Some languages have garbage collection that regularly looks for no-longer-used memory as the program runs; in other languages, the programmer must explicitly allocate and free the memory. Rust uses a third approach: memory is managed through a system of ownership with a set of rules that the compiler checks. If any of the rules are violated, the program won’t compile. None of the features of ownership will slow down your program while it’s running.

How Ownership Works:

There are two primary mechanisms that govern ownership:

  1. Moves: When you assign a value using the = operator, ownership is transferred from the source to the destination variable. The original variable is no longer valid, and its memory is released. This ensures clarity and efficient memory usage.

  2. Borrows and References: When you need to access data owned by another variable without taking ownership, you borrow it using references. References are like pointers that provide temporary access to data. Once the reference goes out of scope, the borrowed data remains valid as long as its original owner is still in scope. This prevents dangling pointers, where you try to access deallocated memory.

Benefits of Ownership:

  • Memory Safety: By eliminating entire classes of memory errors like dangling pointers and memory leaks, ownership fosters the creation of more robust and stable programs.
  • Efficiency: No runtime overhead for garbage collection allows Rust programs to potentially outperform languages that rely on it.
  • Deterministic Memory Usage: The ownership system allows you to predict and control how memory is allocated and released, providing clarity and optimization opportunities.

Rules of Ownership

  • Each value in Rust has an owner.
  • There can only be one owner at a time.
  • When the owner goes out of scope, the value will be dropped.

Code Examples: Understanding Ownership in Action

Let's delve into a code example that demonstrates the concepts of ownership and moves:

Example 1

fn main() {
    let s1 = String::from("hello");
    let s2 = s1;
    println!("{}", s1); // This line would cause a compile error because ownership has been moved.
}

Example 2

fn main() {
    let my_string = String::from("hello");
    takes_ownership(my_string);
    println!("{}", my_string); // This line would cause a compile error because ownership has been moved.
}

fn takes_ownership(some_string: String) {
    println!("{}", some_string); // `some_string` now owns the data.
}

At any time, each value can have a single owner. This is to avoid memory issues like

  • Double free error.
  • Dangling pointers.

How to Fix this?

Option 1: use .clone()

fn main() {
    let s1 = String::from("hello");
    let s2 = s1.clone();
    println!("{}", s1); // Compiles now
}

But what if you want to pass the same string over to the function? You don’t want to clone it, and you want to return back ownership to the original function?
Option 2:

fn main() {
    let s1 = String::from("hello");
    let s2 = takes_ownership(s1);
    println!("{}", s2);
}

fn takes_ownership(some_string: String) -> String {
    println!("{}", some_string); 
    return some_string; // return the string ownership back to the original main fn
}

Option 3

fn main() {
    let mut s1 = String::from("hello");
    s1 = takes_ownership(s1);
    println!("{}", s2);
}

fn takes_ownership(some_string: String) -> String {
    println!("{}", some_string); 
    return some_string; // return the string ownership back to the original main fn
}

Beyond the Basics: Borrowing and Lifetimes

Ownership in Rust is a nuanced topic that goes beyond moves. Borrowing through references introduces the concept of lifetimes, which specify the lifetime of references in relation to the lifetime of their owners. This ensures that borrowed data is always valid and prevents dangling pointers.

Further Learning:

By understanding and effectively utilizing ownership principles, you can unlock the full potential of Rust for safe and efficient memory management in your projects. This README provides a foundational understanding, but don't hesitate to explore the rich resources available to delve deeper into ownership and related concepts in Rust!