Rustにおける `for &value in &vec` の動作解説
Rustのループ構文では、以下のようにベクタを `&` を付けてループする書き方をよく見かけます。
let a = vec![10, 20, 30];
for &value in &a {
println!("{}", value);
}
この構文は一見直感的ではないかもしれませんが、Rustのパターンマッチングと所有権・借用モデルに基づいた省略記法です。
for &value in &a
の意味と展開
このループでは以下のことが自動的に行われています。
&a
によって、Vec<i32>
の各要素に対して&i32
の参照が得られる。for &value
という構文が、その参照をパターンマッチにより即座にデリファレンスし、value
(i32
)を取り出す。
より展開された形で書くと以下のようになります:
for value_ref in &a {
let value = *value_ref;
println!("{}", value);
}
このとき、value_ref
の型は &i32
であり、*value_ref
によって参照(borrow)から実体の値(i32)を取得しています。
_ref
がつくイメージ
Rustでは、for x in &vec
のようなコードは「vec
の要素への参照を x
に1つずつ渡している」動作になります。 そのため for &value in &vec
は、実際には value_ref
という参照を1つずつ取り出し、それを *value_ref
として展開するような処理を、構文上の省略で表現しています。
// イメージとしては次のように展開されている
for value_ref in &vec {
let value = *value_ref;
}
このように、value_ref
は明示されていないだけで、Rustが内部的に扱っている変数と見なすことができます。
所有権・借用の観点から見ると
Rustでは、値の所有権を強く管理しています。
vec
はVec<i32>
→ 中身の値の所有権はvec
にある&vec
によって、その所有権を借りる(borrow)- ループの中では各要素を
&i32
として借用する *value_ref
を使うことでその借用を**参照外し(デリファレンス)**して中身を読み取る
つまり、*value_ref
は「参照から中身を一時的に取り出して読みたい」という、Rustの借用ルールに則った読み取り手段なのです。
以下の図は for &value in &a
の背後で行われている処理のイメージを示しています。
a = vec![10, 20, 30]
↓
+-------------------+
| 10 20 30 | ← 所有権は a にある
+-------------------+
↓
&a(借用)
↓
+------------------------+
| &10 | &20 | &30 | ← 各要素は &i32
+------------------------+
↓ ↓
*value_ref *value_ref ← デリファレンスで値取得
↓ ↓
value=10 value=20
まとめ
for &value in &vec
は、ベクタ要素を参照で借用しつつ、即座にデリファレンスして値を得る構文。- この構文は、Rustの所有権モデルとパターンマッチを活かした書き方。
- 背景では
for value_ref in &vec
→let value = *value_ref;
という処理が行われていると理解すれば、挙動が明確になる。