Skip to main content

🦀 Rust Ownership

·421 words·2 mins·
Table of Contents

Rust Ownership
#

Ownership is Rust's most unique feature and has deep implications for the rest of the language. It enables Rust to make memory safety guarantees without needing a garbage collector.

Ownership Rules
#

Rust's ownership system follows three main rules:

  • 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

Variable Scope
#

A scope is the range within a program for which an item is valid:

fn main() {
    {                      // s is not valid here, not yet declared
        let s = "hello";   // s is valid from this point forward
        // do stuff with s
    }                      // scope is over, s is no longer valid
}

Move Semantics
#

Rust moves ownership by default for types on the heap:

fn main() {
    let s1 = String::from("hello");
    let s2 = s1;  // s1 is moved to s2
    
    // println!("{}", s1); // Error: value borrowed after move
    println!("{}", s2);  // This works
}

Clone
#

To create a deep copy, use the clone method:

fn main() {
    let s1 = String::from("hello");
    let s2 = s1.clone();  // Explicitly copy data
    
    println!("s1 = {}, s2 = {}", s1, s2);  // Both work
}

Copy Types
#

Types stored entirely on the stack use Copy semantics:

fn main() {
    let x = 5;
    let y = x;  // x is copied, not moved
    
    println!("x = {}, y = {}", x, y);  // Both work
}

// Types that implement Copy:
// - All integer types
// - Boolean type
// - All floating-point types
// - Character type
// - Tuples (if they only contain Copy types)

Ownership and Functions
#

Passing a value to a function transfers ownership:

fn main() {
    let s = String::from("hello");
    takes_ownership(s);  // s is moved into the function
    // s is no longer valid here
    
    let x = 5;
    makes_copy(x);  // x is copied
    // x is still valid here
}

fn takes_ownership(some_string: String) {
    println!("{}", some_string);
} // some_string goes out of scope and is dropped

fn makes_copy(some_integer: i32) {
    println!("{}", some_integer);
} // some_integer goes out of scope, nothing special happens

Return Values and Scope
#

Returning values transfers ownership:

fn main() {
    let s1 = gives_ownership();
    let s2 = String::from("hello");
    let s3 = takes_and_gives_back(s2);
}

fn gives_ownership() -> String {
    let some_string = String::from("yours");
    some_string  // Returned and moves out
}

fn takes_and_gives_back(a_string: String) -> String {
    a_string  // Returned and moves out
}

:::

Related