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