Rustのライフタイム
Rustでは安全でない参照を作れない仕組み
これは動かないタイプのスクリプト
code:lifetime.rs
fn main() {
let s = String::from("Hello!");
{
println!("{}", s);
let t = s; // 変数tに変数sの所有権が移動
// 変数tはここで消滅
}
println!("{}", s); // 所有権がないため、ここでエラーになる
}
ライフライム注釈
&i32←これはただの参照(自動的にライフタイムの注釈がつく)
&'a i32←明示ライフタイム付き参照
&'a mut i32←明示ライフタイム付き可変参照
ライフタイム注釈の名前は、変数名のように長くても問題ない。
ただし、'staticは特殊なライフタイムのため注意。(詳しい内容は下記参照)
例えばこんなコードを書いてあるとしよう
code:wrong_lifetime.rs
struct MaxIntStruct {
value: usize
}
impl MaxIntStruct {
fn max(&self, v: &usize) -> &usize {
if v > &self.value { &self.value } else { v }
}
}
fn main() {
let mxint = MaxIntStruct {
value: 23
};
let cint: usize = 20;
println!("Max: {}", mxint.max(&cint));
}
結論、これは動かない。
なぜかというと、vのライフタイムが切れてしまうから。
このソースでは分かりづらいと思うので、max関数がどう解釈されるかというと
code:max_lifetime.rs
impl MaxIntStruct {
fn max<'a, 'b>(&'a self, v: &'b usize) -> &'a usize {
if v > &self.value { &self.value } else { v }
}
}
こうなる。
つまり、引数vはこの関数が終わったら寿命を迎えるため、
引数vの値(参照)が破棄されてしまい、正式な値が返れない。
ライフタイムを揃えるのであれば同じライフタイム注釈にしてしまえばいい。
そうすれば引数vはaグループのライフタイムに入るので破棄される心配がなくなる
これでめでたく動く。
code:lifetime_anno.rs
struct MaxIntStruct {
value: usize
}
impl MaxIntStruct {
fn max<'a>(&'a self, v: &'a usize) -> &'a usize {
if v > &self.value { &self.value } else { v }
}
}
fn main() {
let mxint = MaxIntStruct {
value: 23
};
let cint: usize = 20;
println!("Max: {}", mxint.max(&cint));
}
特殊なライフタイム
ちなみに'staticライフタイムというものがあり、これはプログラムの実行から終了まで永続する特殊なライフタイムがあるようだ。とは言ってもこれをたくさん使うのはまずい気がするが。
P.S. ライフタイム注釈については慣れで書いていかないといかんな・・・。