Rustでは&
は参照(リファレンス)を取る演算子です。
では、なぜポインタ(アドレス)が取得できるかというと、参照はポインタに自動変換することができるようになっているからです。
rust
1let x = 99;
2let ref_x: &u32 = &x;
3let ptr_x: *const u32 = ref_x;
参照とポインタには次の2つの違いあります。
- ポインタは
null
の可能性があるが、参照は null
でないことが保証されている。
- 全ての参照にはライフタイム(有効期間)が設定されており、間違った使い方をするとコンパイルエラーになる。一方、ポインタにはライフタイムは設定されておらず、C++と同じように自分で有効期間を考慮してプログラムを書く必要がある。
前者はC++と同様なので、後者について説明します。
次の例を見てください。
rust
1fn main() {
2 let mut x = 99;
3 let ref_x = &x;
4 x = 10; // error[E0506]: cannot assign to `x` because it is borrowed
5 println!("x = {}", ref_x);
6}
3行目の let ref_x = &x;
で参照を取得し、5行目の println!("x = {}", ref_x);
で参照を使用しているので、この参照の有効期間は3行目から5行目ということになります。この参照が有効な間は元の変数は変更できなくなるで、4行目の x = 10;
で元の変数を変更しようとするとコンパイルエラーになります。
一方、次のように参照ではなくポインタを使用した場合はこのようなチェックは行われません。
rust
1fn main() {
2 let mut x = 99;
3 let ptr_x: *const u32 = &x;
4 x = 10; // コンパイルエラーにならない!
5 println!("x = {}", unsafe { *ptr_x });
6}
3行目の let ptr_x: *const u32 = &x;
で参照を一時的に作成していますが、すぐにポインタに変換され、以後、この参照は使われていないので、参照の有効期間は3~5行目ではなく3行目のみとなります。
そのため、4行目の x = 10;
で元の変数を書き換えても、コンパイルエラーにはなりません。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/09/15 04:08