Rust 所有権
手を動かして考えればよくわかる 高効率言語 Rust 書きかた・作りかた
3章
-
参照渡し call by reference:
関数に引数に指定した変数の参照(変数が指定しているアドレス)が渡されるので、関数内で変更すると呼び出し元も変更される。 -
値渡し call by value
関数に引数に指定した変数のコピーが渡されるので、関数内で変更しても呼び出し元は変更されない。
Pythonでは、
リストなどのオブジェクトの場合→参照渡し
文字列や数値などの定数値の場合→値渡し
Rustでは、
変数の前に&をつける場合→参照渡し
変数の前に&をつけない場合→値渡し
さらに、値渡しで基本型(u32等)以外の型の場合には、所有権の移動が起こる
基本型のデータ(u32等)は、スタック領域に確保されるので直接コピーされる。代入しても所有権のエラー起こらない
エラーではない。Warningはでる。
fn main(){
let a:u32 = 20;
let b = a;
println!("{}", a);
}
基本型以外のデータ(String::from等)は、ヒープ領域に確保され、所有権システムで管理されるので移動処理される。
所有権でのエラー
fn main(){
let a:String::from = "Hello";
let b = a;
println!("{}", a);
}
スタック領域
OSが自動的に必要なときに確保、使用しなくなったら開放
コンパイルする時点でサイズが決まる
ヒープ領域
アプリケーションが動的に確保
サイズ可変
Rustでは
配列:要素の個数を1度決めたら変更できない。スタック領域にメモリ確保される。
let value[i32; 3] = [10, 20, 30];
ベクター型: 要素の個数を変更できる。スタック領域にメモリ確保される。
let value: Vec<i32> = vec![10, 20, 30];
スタック領域にメモリ確保したほうが高速にアクセスできるため、配列よりもベクター型のほうが高速。
所有権が移動してエラー出る
所有権のエラーを出さないためにshow_message
の関数実行後にg1が再度所有権を持つようにする
関数で所有権が移動しない方法として借用がある
関数の引数に参照を指定(&で指定)することが借用
借用には関数の呼び出し(*1)と関数の定義(*2)で参照を使う
関数の戻り値に関数内で作成した変数(所有権)を参照で返すとエラーがでる。
所有権は有効スコープから出ると破棄されるので、関数の戻り値に参照を指定しても所有権が破棄されているのでエラーが生じる
エラーを出さないためには、関数の戻り値に実体を返すようにする。つまり、関数の戻り値(*2)に所有権が移動するようにする。
関数の中で引数の値を変更したい場合、関数の定義で「&mut 型」、関数呼び出し時に「&mut 変数」の2つで設定し、ミュータブルな参照であることを明示する。
変数の参照から実体を取り出す(参照外し、dereference)場合、*変数名で書く。