ライフタイム
ライフタイム はコンパイラ(借用チェッカーと呼ばれる場合もあります)が、全ての借用に問題がないことを確認するために使用する仕組みです。正確にいうと、変数のライフタイムは作成時に開始し、破棄された時に終了します。ライフタイムとスコープは同時に語られることが多いですが、同じものではありません。
例として&
を用いて変数を借用する場合をあげましょう。借用のライフタイムは宣言時に決定し、そこから貸し手が破棄されるまで続きます。しかしながら、借用のスコープは参照が使われる際に決定します。
以下の例からこのセクションの残りでは、ライフタイムとスコープの関係、そしてそれらがいかに異なるものであるかを見ていきます。
// Lifetimes are annotated below with lines denoting the creation // and destruction of each variable. // `i` has the longest lifetime because its scope entirely encloses // both `borrow1` and `borrow2`. The duration of `borrow1` compared // to `borrow2` is irrelevant since they are disjoint. // 以下では、変数の作成から破棄までのライフタイムを線で示しています。 // `i`は最長のライフタイムを持ち、そのスコープは`borrow1`および`borrow2` // のスコープを完全に包含します。`borrow1`と`borrow2`の存続期間は一切重なりません。 fn main() { let i = 3; // Lifetime for `i` starts. ────────────────┐ // `i`のライフタイム開始 │ // │ { // │ let borrow1 = &i; // `borrow1` lifetime starts. ──┐│ // `borrow1`のライフタイム開始 ││ // ││ println!("borrow1: {}", borrow1); // ││ } // `borrow1` ends. ─────────────────────────────────┘│ // `borrow1`終了 │ // │ // │ { // │ let borrow2 = &i; // `borrow2` lifetime starts. ──┐│ // `borrow2`のライフタイム開始 ││ // ││ println!("borrow2: {}", borrow2); // ││ } // `borrow2` ends. ─────────────────────────────────┘│ // `borrow2`終了 │ // │ } // Lifetime ends. ─────────────────────────────────────┘ // ライフタイム終了
ここで、一切の名前や型がライフタイムにアサインされていないことに注意しましょう。これにより、ライフタイムの使われ方がこれから見ていくようなやり方に制限されます。