DEV Community

Cover image for Ownership in Rust
Sumana
Sumana

Posted on

Ownership in Rust

Ownership is Rust’s memory management system based on three rules:
each value has a single owner, only one owner can exist at a time, and a value is dropped when its owner goes out of scope.
Values are either moved (ownership is transferred) or copied (for simple Copy types like integers).

This system allows Rust to guarantee memory safety at compile time, without a garbage collector.


Value is dropped when its owner goes out of scope

fn main() {
    let name = String::from("Pixy");
    take_ownership(name);
}

fn take_ownership(s: String) {
    println!("{}", s);
} // s goes out of scope here → dropped
Enter fullscreen mode Exit fullscreen mode

Here, ownership of name is moved into take_ownership.
When the function ends, s goes out of scope and Rust automatically frees the memory.


Ownership is transferred (moved)

fn main() {
    let username = String::from("Pixy");
    print_user(username);
}

fn print_user(name: String) {
    println!("User: {}", name);
}
Enter fullscreen mode Exit fullscreen mode

Passing username into print_user moves ownership.
After the move, main can no longer access username. Only one owner exists at a time.


Function takes ownership

fn take(s: String) {
    println!("{}", s);
}

fn main() {
    let name = String::from("Pixy");
    take(name);
}
Enter fullscreen mode Exit fullscreen mode

The function parameter s becomes the new owner.
Once take finishes, the value is dropped.


Borrowing with immutable references

fn borrow(s: &String) {
    println!("{}", s);
}

fn main() {
    let name = String::from("Pixy");
    borrow(&name);
    println!("{}", name);
}
Enter fullscreen mode Exit fullscreen mode

Here, the function borrows name using &String.
Ownership stays in main, so name is still usable afterward.


Multiple immutable references at the same time

Rust allows multiple immutable references to the same value at the same time, as long as no one is mutating it.

fn main() {
    let name = String::from("Pixy");

    let ref1 = &name;
    let ref2 = &name;

    println!("{} {}", ref1, ref2);
}
Enter fullscreen mode Exit fullscreen mode

This works because:

  • Both ref1 and ref2 are read-only
  • Ownership still stays with name
  • No data race is possible when only reading

Borrowing rule summary

  • ✅ Multiple immutable references are allowed
  • ✅ One mutable reference is allowed
  • ❌ Mutable and immutable references cannot coexist

This rule is what lets Rust be strict and flexible at the same time.


Borrowing with mutable references

fn change(s: &mut String) {
    s.push_str("!");
}

fn main() {
    let mut name = String::from("Pixy");
    change(&mut name);
}
Enter fullscreen mode Exit fullscreen mode

Mutable borrowing allows modifying a value without taking ownership.
Rust ensures only one mutable reference exists at a time, preventing data races.


Final thought

Ownership, moves, and borrowing work together to prevent memory leaks, use-after-free errors, and data races — all without runtime overhead.

Top comments (0)