3
1

More than 1 year has passed since last update.

Rustの生存期間

Posted at

ローカル変数の借用

  • Rustコンパイラは、プログラム中の全ての参照型に対して、その参照の使用方法によって生じる制約を反映した生存期間(lifetime)を割り当てる
    • 生存期間とは、プログラム実行中のある参照が安全に利用できる期間

fn main() {
    let r;
    {
        let x = 1;
        r = &x;
    }
    assert_eq!(*r, 1);
}

&xの生存期間

x.png

rに格納された値に必要な最低限の生存期間

y.png

エラーになる原因

z.png

改善例

fn main() {
    let x = 1;
    {
        let r = &x;
        assert_eq!(*r, 1);
    }
}

a.png

diff

--- 改善前
+++ 改善後
@@ -1,8 +1,7 @@
 fn main() {
-    let r;
+    let x = 1;
     {
-        let x = 1;
-        r = &x;
+        let r = &x;
+        assert_eq!(*r, 1);
     }
-    assert_eq!(*r, 1);
 }

仮引数として参照を受け取る場合

  • デフォルトでは生存期間の記述は省略されている
    • fn f<'a>(p: &'a i32)
    • この関数が「任意の生存期間'a を持つ i32 への参照 」を引数として取ることを意味
  • staticの生存期間はプログラムの開始から終了まで
    • 引数の生存期間を合わせるために明示的に生存期間を指定する必要がある場合がある
main.rs
static mut STASH: &i32 = &128;

fn f(p: &'static i32) {
    unsafe {
        STASH = p;
    }
}

fn main() {
    unsafe {
        println!("{}", STASH);
        f(&256);
        println!("{}", STASH);
    }
}

$ cargo run
128
256

参照を含む構造体

main.rs
struct S<'a> {
    r: &'a i32,
}

struct D<'a> {
    s: S<'a>,
}

fn main() {
    let x = 10;
    let s = S { r: &x };
    assert_eq!(*s.r, 10);

    let d = D { s };
    assert_eq!(*d.s.r, 10);
}

個別の生存期間のパラメータ

  • s.xの生存期間とs.yの生存期間が異なるので、異なる生存期間を設定する必要がある
    • 改善前のコードでは r = s.x により x の方が長い生存期間となっている
  • 最も単純な定義から始めて、コンパイルできるまで、徐々に制約を緩めていくアプローチがよい
    • 安全でない限りコードがコンパイルできないので、問題が明らかになるまで待つで問題ない

改善前

main.rs
/// xとyに対して同じ生存期間を設定
struct S<'a> {
    x: &'a i32,
    y: &'a i32,
}

fn main() {
    let x = 10;
    let r;
    {
        let y = 20;
        {
            let s = S { x: &x, y: &y };
            r = s.x
        }
    }
    println!("{}", r);
}

改善後

main.rs
/// xとyに対して異なる生存期間を設定
struct S<'a, 'b> {
    x: &'a i32,
    y: &'b i32,
}

fn main() {
    let x = 10;
    let r;
    {
        let y = 20;
        {
            let s = S { x: &x, y: &y };
            r = s.x
        }
    }
    println!("{}", r);
}

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1