【Rust】所有権・移動・参照

JavaやJavaScriptなどでは、ヒープ領域に確保したメモリは誰からも参照されなくなった後にガーベジコレクションによって解放される。Rustでは、ただ一つの変数がヒープ上のメモリの所有権を持ち、所有者がスコープから消えた時点でヒープ領域も解放される。

fn func1() {
    let name = String::from("ABC");
    println!("{}", name);
}

関数に変数を渡すと所有権が移る

fn func1() {
    let name = String::from("ABC");
    println!("{}", name);
    func2(name);
    println!("{}", name);
}

fn func2(name: String){
    println!("{}", name);
}

所有権を返してもらうこともできる

fn func1() {
    let name = String::from("ABC");
    println!("{}", name);
    name = func2(name);
    println!("{}", name);
}

fn func2(name: String) -> String{
    println!("{}", name);
    name
}

&で参照を渡すことで、所有権を移さないまま関数を呼び出すこともできる

fn func1() {
    let name = String::from("ABC");
    println!("{}", name);
    name = func2(&name);
    println!("{}", name);
}

fn func2(name: &String){
    println!("{}", name);
}

関数内で他の変数に渡しただけでも所有権の移転が発生する

fn func1() {
    let s1 = String::from("ABC");
    {
        let s2 = s1;
        println!("{}", s2);
    }
}

c++でお馴染みのswap

#include <cstdio>

void swap(int &a, int &b)
{
    int temp;;
    temp = a;
    a = b;
    b = temp;
}

void swap_pointer(int *a, int *b){
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

int main() {
    int x = 5;
    int y = 8;

    swap(x, y);
    printf("%d, %d\n", x, y);

    swap_pointer(&x, &y);
    printf("%d, %d\n", x, y);

    return(0);
}

rustでswapを書こうとすると上手くいかない

fn func1() {
    let s1 = String::from("ABC");
    {
        let s2 = s1;
        println!("{}", s2);
    }
}

fn func2(name: &String){
    println!("{}", name);
}

fn main(){
    let mut x: i32 = 5;
    let mut y: i32 = 8;
    swap(&x, &y);
    println!("x:{} y:{}", x, y);
}

$ ./main
x:5 y:8