到達点は、値を渡した後に使えるかを予測することです。前提は第03回です。
誰が資源を片付けるか
Stringは文字列データを所有します。所有する値を別の変数へ移すと、元の変数からは使えなくなる場合があります。これをMoveと呼びます。同じ資源を二度解放したり、解放後に参照したりしないよう、コンパイラが利用関係を確認します。
fn consume(text: String) -> usize {
text.len()
}
fn main() {
let original = String::from("Rust");
let independent = original.clone();
let moved = original;
println!("{moved} {independent}");
let bytes = consume(moved);
println!("{bytes}");
let x = 10_u32;
let y = x;
println!("{x} {y}");
}
src/main.rsで実行すると、Rustが二つ、4、10が二つ表示されます。Stringのcloneは独立した文字列データを作ります。u32はCopyを実装しており、代入後もxを使えます。Moveが常に大量データの物理的コピーを意味するわけではありません。
エラーになる例を読む
次は意図的にコンパイルできない、独立した例です。
fn main() {
let first = String::from("Rust");
let second = first;
println!("{first} {second}");
}
firstはsecondへ移動した後なので、利用を拒否されます。修正は必ずcloneではありません。単に読むだけなら借用で足ります。独立した値が本当に必要か、所有権を受け取る必要があるかを考えるのが次の回です。
Dropと共有所有
通常、所有する値がスコープを出るとDropによる後始末が行われます。RustにはRcやArcという共有所有の仕組みもありますが、参照カウントなど別の費用や制約があります。所有権を理解せず、すべてを共有ポインタへ入れる必要はありません。
練習と解答
練習:consumeへindependentを渡した後でindependentを表示したい場合、どんな選択肢がありますか。
解答:消費する必要がなければ引数を &str に変えて借用します。元と独立した所有物が必要ならcloneを渡します。関数から元のStringも返す方法もありますが、長さを読むだけなら借用が自然です。
公式資料
所有権を参照できます。
Rust全20回の目次 | 前の回 | 次の回