この記事で書くこと
rustの参照と借用についての説明です。
所有権については別に記事を書いていますので、必要あればご確認ください。
参照と借用
参照とは
安全なポインタ変数のことです。ポインタ変数とは、変数のアドレスが保管されている変数です。ポインタ変数に関しては、こちらを参照。
以下のコードを例に解説して行きます。
let x = 5;
println!("x = {}",x);
println!("&x = {:p}",&x);
let rx = &x;
println!("rx = {:p}",rx);
println!("&rx = {:p}",&rx);
実行結果
x = 5
&x = 0x16b5c9e64
rx = 0x16b5c9e64
&rx = 0x16b5c9ef0
上記の実行結果を図にすると以下のようになります。
まず5という値が変数xに束縛されます。この値は0x16b5c9e64というアドレスにあります。rxにこのアドレスの値を束縛します。rx自体のアドレスは0x16b5c9ef0になります。
このアドレスは動作環境によって変わります。
借用とは
参照を作ることを借用と言います。この行ではrxはxの値を借用していることになります。
let rx = &x;
借用のルール
参照は安全なポインタ変数と言いましたが、これは借用のルールが定められているからです。借用のルールを破るとコンパイルできません。
借用のルールは、以下です。
不変参照をたくさんor可変参照1つ
まず、不変参照、可変参照についてです。
不変参照とは
参照元の値を変更できない参照のことです。以下のコードはコンパイルできません。これはrxが不変参照なのに値を変更しようとしたからです。借りてきたものを勝手に変更するのはやめましょう.
let x = 5;
let rx = &x;
*rx += 10; // <- not allowed
不変参照たくさん
不変参照はいくつ作ってもOKです。
let x = 5;
let rx = &x;
let rx2 = &x;
let rx3 = &x;
println!("{} {} {}", rx, rx2, rx3);
実行結果
5 5 5
可変参照とは
参照もとの値を変更できる参照のことです。借用するときにmutをつけると可変参照にすることができます。不変参照と違って値を変更することができます。参照元の変数も可変である必要があります。
let mut x = 5;
let rx = &mut x;
println!("{}",rx);
*rx += 10;
println!("{}",rx);
値を変更するときにつけた*は参照外し(デリファレンス)といいます。参照はずしについてはこちらを参照ください。
可変参照は1つだけ
同時に作れる可変参照は1つだけです。
可変参照が複数だとコンパイルできない
以下のコードは可変参照が2つになるため、コンパイルできません。
let mut x = 5;
let rx = &mut x;
let rx1 = &mut x; // not allowed
println!("{}",rx);
*rx += 10;
println!("{}",rx);
しかし、rustのコンパイラさんは賢いので、以下のコードはコンパイルさせてくれます。実はrx1を作ったとき、rxが破棄されています。なので、rxが再び使われないなら、コードは合法です。
let mut x = 5;
let rx = &mut x;
let rx1 = &mut x; // ok
println!("{}",rx1);
rxを使ってしまった場合、コンパイルはできなくなります。
let mut x = 5;
let rx = &mut x;
let rx1 = &mut x; // not allowed
println!("{}",rx);
可変参照1つと不変参照でもコンパイルできない
可変参照があるときは、不変参照も作ることができません。
let mut x = 5;
let rx = &mut x;
let rx1 = &x; // not allowed
println!("{}",rx);
最後に
参照についての基本的な内容については以上です。ご意見、ご感想、指摘等あればコメントお願いします。
また、参照だけでなく、所有権についても知りたい方はこちらもご覧ください。
コメント