Rust

【Rust】第3章第3回:ライフタイム(Lifetime)の基本と注釈の使い方

本記事では、Rustの「ライフタイム(Lifetime)」の基本概念と、ライフタイム注釈の使い方について解説します。Rustのメモリ管理を理解し、安全なコードを記述できるようになりましょう。

0. 記事の概要

この記事を読むメリット

  • Rustのライフタイムの基本を理解: 参照が有効な範囲を正しく管理できるようになります。
  • エラーを防ぐ: 「借用が有効期間を超えています」エラーの原因と対処法を学べます。
  • より安全なコードを書く: 明示的なライフタイム注釈を活用し、バグの少ないプログラムを実装できます。

この記事で学べること

  • ライフタイムの基本概念
  • ライフタイム注釈の使い方
  • ライフタイムに関連するエラーの回避方法

1. ライフタイムとは?

1.1 ライフタイムの基本概念

ライフタイムは、参照が有効である期間を示します。Rustでは、メモリ安全性を保証するためにライフタイムを追跡します。

fn main() {
    let r;
    {
        let x = 5;
        r = &x;
    } // xはここでスコープを抜ける

    println!("r: {}", r); // エラー!xのライフタイムが終了
}

動作解説

変数rxの参照を保持していますが、xはスコープを抜けて無効になります。そのため、コンパイルエラーが発生します。

2. ライフタイム注釈の基本

2.1 明示的なライフタイム注釈

ライフタイムを明示的に指定することで、Rustに参照の有効期間を伝えることができます。

fn longest<'a>(s1: &'a str, s2: &'a str) -> &'a str {
    if s1.len() > s2.len() { s1 } else { s2 }
}

fn main() {
    let str1 = "Hello";
    let str2 = "Rust";
    let result = longest(str1, str2);
    println!("長い文字列: {}", result);
}

動作解説

関数longestはライフタイム注釈'aを用いることで、参照が適切な範囲で有効になることを保証しています。

3. ライフタイムの適用範囲

3.1 構造体へのライフタイム適用

ライフタイムは構造体のフィールドにも適用できます。

struct Text<'a> {
    content: &'a str,
}

fn main() {
    let phrase = "Rust is great!";
    let text = Text { content: phrase };
    println!("{}", text.content);
}

動作解説

このコードでは、ライフタイム'aを指定することで、構造体のフィールドが有効な間のみ参照が保持されることを保証しています。

4. よくあるエラーと対処法

  • 「borrowed value does not live long enough」エラー: 参照のライフタイムが短すぎる場合に発生。
  • 「missing lifetime specifier」エラー: ライフタイムを明示しないとコンパイラが解決できない場合に発生。

5. まとめ

本記事では、Rustのライフタイムの基本概念、ライフタイム注釈の使い方、エラーの回避方法について解説しました。次回は、可変借用と不変借用の違いと注意点について詳しく学びます。