English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Rust ファイルとIO

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

この戻り値にはライフサイクルコメントがありませんが、加えることもできます。これは歴史的な問題であり、初期のRustはライフサイクルの自動判定をサポートしていませんでしたが、主流の安定版のRustはこの機能をサポートしています。

静的生命周期

ライフサイクルコメントには特別なものがあります:'static 。ダブルクオートで囲まれたすべての文字列定数は、'static str としての正確なデータ型であり、'static はプログラムの実行開始から実行終了までのライフサイクルを表します。

例
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

}