関数

省略をしない場合、ライフタイムのシグネチャ(e.g. <'a>)を持つ関数にはいくつかの制限があります。

  • 全ての参照においてライフタイムを明示しなくてはなりません。
  • 返り値となる参照はすべて引数と同じライフタイムか、staticライフタイムを持たなくてはなりません

加えて、引数のない関数から参照を返すことは、それが結果的に無効なデータへの参照になるならば、禁止されています。ライフタイムを持つ関数の例をいくつか示します。

// 引数として`'a`のライフタイムで参照を一つ取ります。最低でもこの関数
// と同じだけの長さでなくてはなりません。
fn print_one<'a>(x: &'a i32) {
    println!("`print_one`: x is {}", x);
}

// ミュータブルな参照でも同様。
fn add_one<'a>(x: &'a mut i32) {
    *x += 1;
}

// 異なるライフタイムを持つ複数の引数がある場合。
// ここでは1種類のライフタイムでも問題ありませんが、より複雑なケースでは
// 異なるライフタイムが必要になる場合があります。
fn print_multi<'a, 'b>(x: &'a i32, y: &'b i32) {
    println!("`print_multi`: x is {}, y is {}", x, y);
}

// 受け取った参照をそのまま返すことに問題ありませんが、適切なライフタイム
// でなくてはなりません。
fn pass_x<'a, 'b>(x: &'a i32, _: &'b i32) -> &'a i32 { x }

// `'a`は関数より長くなくてはならないため上の関数は正しくありません。
// ここでは、`&String::from("foo")`は`String`のデータとそれへの参照を作ります。
// その後データはスコープを抜けるとともに破棄されます。そのため、
// 不適切なデータに対する参照を返すことになってしまいます。

fn main() {
    let x = 7;
    let y = 9;
    
    print_one(&x);
    print_multi(&x, &y);
    
    let z = pass_x(&x, &y);
    print_one(z);

    let mut t = 3;
    add_one(&mut t);
    print_one(&t);
}

参照

関数