Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

Rust Dictionary

  1. Home
  2. Rust Dictionary
  3. Ownership / Move

Ownership / Move

Since: Rust 1.0(2015)

Rust's ownership system enforces a unique rule: every value has exactly one owner. This guarantees memory safety at compile time. When the owner goes out of scope, the value is automatically freed.

Syntax

let variable1 = value;
let variable2 = variable1; // Ownership of variable1 moves to variable2 (variable1 becomes invalid).

// Moving ownership into a function
fn function_name(arg: Type) { ... }
function_name(variable); // Ownership of variable moves into the function.

// Explicitly free memory
drop(variable);

Overview

RuleDescription
Single ownerEach value has exactly one owning variable at any given time.
Freed at scope endWhen the owner goes out of scope, the value's memory is automatically freed.
Move semanticsAssignment or passing to a function moves ownership, making the original variable unusable.
drop()Used to immediately free a variable that holds ownership.

Sample Code

sample_ownership_move.rs
fn take_ownership(s: String) {
    println!("{}", s);
} // s is freed here.

fn main() {
    let s1 = String::from("hello");
    let s2 = s1; // Ownership of s1 moves to s2.
    // println!("{}", s1); // Error: s1 is no longer valid.
    println!("{}", s2); // Prints "hello".

    let s3 = String::from("world");
    take_ownership(s3); // Ownership of s3 moves into the function.
    // println!("{}", s3); // Error: s3 is no longer valid.

    // Immediately free s4 with drop().
    let s4 = String::from("drop me");
    drop(s4);
    // println!("{}", s4); // Error: s4 has already been freed.

    // Types that implement the Copy trait are copied instead of moved.
    let x = 5;
    let y = x; // x is still valid.
    println!("x={}, y={}", x, y); // Both are usable.
}

Compile with the following command:

rustc ownership_move.rs
./ownership_move
hello
world
x=5, y=5

Advanced Patterns

sample_ownership_advanced.rs
fn create_name() -> String {
    String::from("user_a") // ownership is returned to the caller
}

fn process(name: String) -> String {
    format!("name: {}", name) // takes and returns ownership
}

// Pattern 2: Copy types are duplicated automatically
fn show_i32(n: i32) {
    println!("{}", n);
}

// Pattern 3: Clone copies heap data explicitly
fn show_string(s: &String) {
    println!("{}", s);
}

use std::thread;

fn main() {
    // Returning ownership
    let name = create_name();
    let result = process(name); // ownership of `name` moves into process()
    println!("{}", result);
    // `name` cannot be used here

    // Copy: i32 is Copy, so no move occurs
    let x = 42i32;
    show_i32(x);
    println!("x is still usable: {}", x); // OK

    // Clone: explicitly copy a String
    let s = String::from("user_c");
    let s_clone = s.clone();
    show_string(&s);
    show_string(&s_clone);
    println!("both usable: {} / {}", s, s_clone);

    // move closure: the closure takes ownership of captured variables
    let message = String::from("hello");
    let handle = thread::spawn(move || {
        println!("from thread: {}", message); // ownership moved here
    });
    // println!("{}", message); // compile error: moved
    handle.join().unwrap();
}

Compile with the following command:

rustc sample_ownership_advanced.rs
./sample_ownership_advanced
name: user_a
x is still usable: 42
user_c
user_c
both usable: user_c / user_c
from thread: hello

Common Mistakes

Common mistake 1: using a variable after its ownership has moved

Passing a value to a function or assigning it to another variable transfers ownership. The original variable cannot be used after the move.

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

fn main() {
    let s = String::from("user_e");
    take_ownership(s); // ownership of `s` is moved

    // Compile error: `s` has been moved
    // println!("{}", s);
}

The same logic can also be written as:

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

fn main() {
    let s = String::from("user_e");

    // Option 1: pass a reference — ownership stays with the caller
    println!("{}", &s);
    take_ownership(s.clone()); // clone a copy to pass
    println!("{}", s); // s still usable
}

Common mistake 2: confusing Copy and Clone

Types that implement Copy (like i32, bool, f64) are duplicated implicitly on assignment. Types like String and Vec do not implement Copy and must be cloned explicitly.

fn main() {
    // i32 is Copy: assignment duplicates the value
    let x: i32 = 10;
    let y = x;
    println!("{} {}", x, y); // both usable

    // String is not Copy: assignment moves ownership
    let s1 = String::from("hello");
    let s2 = s1;
    // println!("{}", s1); // compile error: s1 was moved

    // Clone explicitly copies the heap data
    let s3 = String::from("world");
    let s4 = s3.clone();
    println!("{} {}", s3, s4); // both usable
}

Details

Rust's ownership system guarantees memory safety without a garbage collector. When a value goes out of scope, drop() is called automatically and the memory is freed (the RAII pattern). RAII (Resource Acquisition Is Initialization) is a pattern that ties resource acquisition and release to a variable's lifecycle.

Using a variable after its ownership has been moved causes a compile error. If you need to use a value in multiple places, use borrowing (& references) or clone().

Types that implement the Copy trait — such as integers, floating-point numbers, booleans, and chars — are copied on assignment, so the original variable remains valid.

If you find any errors or copyright issues, please .