所有権とムーブ
変数は自分自身のリソースを解放する責任を負うため、 リソースは所有者を 1 つしか持てません。これにより、リソースが 複数回解放されることを防ぎます。すべての変数が リソースを所有しているわけではないことに注意してください(例: references)。
代入(let x = y)を行うときや、関数の引数を値渡しで渡すとき (foo(x))、リソースの_所有権_が移されます。Rust 用語では、 これは_ムーブ_として知られています。
リソースをムーブした後、以前の所有者はもう使用できません。これにより、 ダングリングポインターの作成を回避できます。
// この関数はヒープに割り当てられたメモリの所有権を受け取ります fn destroy_box(c: Box<i32>) { println!("Destroying a box that contains {}", c); // `c` は破棄され、メモリは解放されます } fn main() { // _スタック_ に割り当てられた整数 let x = 5u32; // `x` を `y` に *コピー* します - リソースはムーブされません let y = x; // 両方の値を独立して使用できます println!("x is {}, and y is {}", x, y); // `a` は _ヒープ_ に割り当てられた整数へのポインターです let a = Box::new(5i32); println!("a contains: {}", a); // `a` を `b` に *ムーブ* します let b = a; // `a` のポインターアドレスが(データではなく)`b` にコピーされます。 // 両方とも同じヒープに割り当てられたデータへのポインターですが、 // 今では `b` がそれを所有しています。 // エラー! `a` はデータにアクセスできなくなりました。なぜなら、もはや // ヒープメモリを所有していないからです //println!("a contains: {}", a); // TODO ^ この行をコメント解除してみてください // この関数は `b` からヒープに割り当てられたメモリの所有権を受け取ります destroy_box(b); // この時点でヒープメモリは解放されているため、この操作は // 解放済みメモリの参照外しになりますが、コンパイラによって禁止されています // エラー! 前のエラーと同じ理由です //println!("b contains: {}", b); // TODO ^ この行をコメント解除してみてください }