本文へスキップ
BecomeCoder

Rustコース · 第4章 所有権 · レッスン15

所有権の3つのルール

ブラウザで完結

導入

所有権は、たった3つのルールに集約されます。まずこの3つを丸ごと頭に入れてしまいましょう。以降のレッスンは、すべてこの3ルールの具体例です。

説明

Rust の所有権の3ルールは次のとおりです。

  1. Rust の各値には、所有者(owner) と呼ばれる変数がただ1つある。
  2. 所有者は同時に1人だけ
  3. 所有者がスコープ(有効範囲)を抜けると、値は破棄(drop)される

「スコープ」とは、変数が有効な範囲——ふつうは { } で囲まれた区間です。

fn main() {
    // ここではまだ s は存在しない

    let s = String::from("hello");   // s が誕生。ヒープに "hello" を確保し、s がその所有者に
    println!("{s}");                  // s は有効。使える

}   // ← ここで s のスコープが終わる。ルール3により s が drop され、ヒープが自動解放
  • let s = String::from("hello"); の瞬間、ヒープ上の "hello"所有者は s(ルール1・2)。
  • main} に来ると s はスコープを抜け、Rust が自動で drop(解放処理)を挿入します(ルール3)。C言語で言えば free(s) を、Rust があなたの代わりに正しい位置に書いてくれるイメージです。
graph TD
    a["let s = String::from(...)<br/>s がヒープの所有者になる"] --> b["s を使う"]
    b --> c["スコープの } に到達"]
    c --> d["Rust が自動で drop(s) を挿入<br/>ヒープを解放"]

このルールがあるおかげで、解放し忘れ(誰かが必ず所有者で、スコープ終わりに解放される)も、二重解放(所有者は1人だけなので2回解放されない)も、原理的に起きません。しかも判断はコンパイル時。実行時のGCは不要です。

問題は「所有者は1人だけ」というルール2です。では、String を別の変数に代入したり、関数に渡したりすると、所有権はどうなるのでしょう? それが次のレッスンの「ムーブ」です。

試すには

3ルールを声に出して覚えてしまいましょう。「①値には所有者が1人 ②同時に1人だけ ③所有者がスコープを抜けたら破棄」。この3行が、これから出てくるあらゆる「借用」「ライフタイム」の土台になります。

実際に動かしてみよう

下のエディタにRustを書いて「実行」を押すと、学習用シミュレータが println! の出力を表示します(本物のrustcではなく、教材の範囲を再現した軽量エンジンです)。struct・enum・match・トレイト・Vec/String/HashMap・Option/Result なども動きます。本文の例を書き換えて動かしてみましょう(所有権・借用チェッカーのコンパイルエラーは再現しないため、動きの確認用として使ってください)。

Rust — ブラウザ内で実行(学習用シミュレータ)

Rustの教材サブセットを動かす学習用シミュレータを読み込みます(本物のrustcではなく、動きを再現した軽量な自作エンジンです)。
スクロールして表示された時点でも自動で読み込まれます。