関数
elisionを無視すると、ライフタイムを持つ関数シグネチャにはいくつかの制約があります。
- すべての参照には、注釈付きのライフタイムがなければなりません。
- 返されるすべての参照は、入力と同じライフタイムを持つか、
staticでなければなりません。
さらに、入力なしで参照を返すことは、無効なデータへの参照を返すことになる場合は禁止される点に注意してください。次の例は、ライフタイムを持つ関数の有効な形式をいくつか示しています。
// 関数と少なくとも同じ長さだけ生存しなければならない、 // ライフタイム`'a`を持つ1つの入力参照。 fn print_one<'a>(x: &'a i32) { println!("`print_one`: x is {}", x); } // 可変参照でもライフタイムを使用できます。 fn add_one<'a>(x: &'a mut i32) { *x += 1; } // 異なるライフタイムを持つ複数の要素。この場合、両方が同じ // ライフタイム`'a`を持っていても問題ありませんが、 // より複雑な場合には、異なるライフタイムが必要になることがあります。 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 } //fn invalid_output<'a>() -> &'a String { &String::from("foo") } // 上記は無効です。`'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); }