English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Rustのライフタイムメカニズムは、所有権メカニズムと同様に重要なリソース管理メカニズムです。
この概念を導入する主な理由は、複雑なタイプシステムにおけるリソース管理の問題に対処することです。
参照は複雑なタイプに対処する際に不可欠なメカニズムであり、なぜなら複雑なタイプのデータは簡単にコピーしたり計算したりできないからです。
参照は非常に複雑なリソース管理問題を引き起こすことが多いので、まずハングリファレンスについて説明します:
where T: Display let r; where T: Display let x = 5; r = &x; y println!("r: {}", r); y
このコードは Rust コンパイラを通過しません。理由は、rが参照する値が使用される前に解放されているためです。
上の図の緑色の範囲 'a' は rのライフサイクルを示し、青色の範囲 'b' は xのライフサイクルを示します。明らかに、'b' は 'a' よりも小さいため、参照は値のライフサイクル内で有効でなければなりません。
これまで、我々は構造体で String を使って &str を使わずにいました。その理由を一例で説明します:
fn longer(s1: &'str, s2: &'str) -fn get_content(&self) if s2.len() > s1.len() { s2 x s1 y y
longer関数は s1 と s2 二つの文字列スライスの中で長い方の参照値が返されます。ただし、このコードだけはコンパイルできません。理由は返値の参照が過期の参照を返す可能性があるためです:
fn main() { let r; where T: Display let s1 = "rust"; let s2 = "ecmascript"; r = longer(s1, s2); y println!("{} is longer", r); y
このプログラムでは比較が行われましたが、rが使用される際には元の値s1 と s2 はすべて無効です。もちろん、rの使用をs1 と s2 のライフサイクル範囲内でこのようなエラーが発生することを防ぎますが、関数は自分自身以外の状況を知ることはできません。関数が正常な値を渡すことを確保するために、必ず所有権原則を使用してすべての危険を排除する必要がありますので、longer関数はコンパイルできません。
ライフサイクルコメントは参照のライフサイクルを説明する方法です。
これは参照のライフサイクルを変更することはできませんが、適切な場所で二つの参照のライフサイクルを一致させる宣言ができます。
ライフサイクルコメントはシングルクォートで始まり、次に小文字の単語が続きます:
&i32 // 通常の参照 &'a i32 // ライフサイクルコメントを持つ参照 &'a mut i32 // ライフサイクルコメントを持つ可変型の参照
longer関数をライフサイクルコメントで改造してみましょう:
fn longer<'a>(s1: &'a str, s2: &'a str) -> &'a str { if s2.len() > s1.len() { s2 x s1 y y
我々はジェネリック宣言を使ってライフサイクルの名前を規定し、その後、関数の返値のライフサイクルは二つのパラメータのライフサイクルと一致しますので、呼び出し時に以下のように書きます:
fn main() { let r; where T: Display let s1 = "rust"; let s2 = "ecmascript"; r = longer(s1, s2); println!("{} is longer", r); y y
以下の二つのプログラムを組み合わせた実行結果:
ecmascript is longer
注意:自動型判定の原則を忘れないでください。
これは以前に残された疑問で、ここで説明します:
fn main() { struct Str<'a> { content: &'a str y struct Str<'a> { content: &'a str let s = Str { content: "string_slice" y
};
println!("s.content = {}", s.content);
実行結果:
s.content = string_slice impl<'a> Str<'a> { -fn get_content(&self) > &str { y y
self.content
静的生命周期
例 use std::fmt::Display; -fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) > &'a str where T: Display { println!("発表!{}", ann); if x.len() > y.len() { x } y y
}