Rustの所有権モデルを理解する
所有権の基本ルールとムーブセマンティクスを理解し、double-freeのような一般的なメモリエラーを防ぐ仕組みを学びます。
「Rustの所有権モデルを理解する」はCoddyKit上の無料Learn Rust Codingレッスンです。 これはレッスン1/3です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはLearn Rust Coding学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Learn Rust Codingコースには全3レッスンが含まれています。
Rustの所有権とは
Rustの所有権システムは、プログラムによるメモリの使用方法を管理する一連の規則です。ガベージコレクターなしでメモリ安全性を実現するための中核概念です。
- ダングリングポインターが発生しません。
- 二重解放エラーが発生しません。
- 並行コードでデータ競合が発生しません。
Rustは、これらの規則をコンパイル時に検査します。
スタックとヒープのメモリ
プログラムは主に2つのメモリ領域、スタックとヒープを使用します。
- スタック:整数、ブール値、サイズが既知の型など、高速に扱える固定サイズのデータを格納します。データは順番に積み上げられ、順番に取り出されます。
- ヒープ:
StringやVecなど、サイズが可変で比較的低速なデータを格納します。データはアロケーターによって要求され、返却されます。
所有権は主にヒープ上のデータを管理し、安全な使用と解放を保証します。
ルール1:すべての値には所有者がいる
所有権の最初のルールは単純です。Rustの各値には、その所有者と呼ばれる変数があります。
箱に貼られたラベルのようなものだと考えてください。以下では、変数sが文字列「hello」の所有者です。
fn main() {
let s = String::from("hello"); // s owns "hello"
println!("{}", s);
}ルール2:同時に所有者になれるのは1つだけ
2つ目のルールは次のとおりです。どの時点でも、1つの値の所有者は1つだけです。これはメモリに関する問題を防ぐために重要です。
ヒープ上に存在するStringのような複雑な値を、ある変数から別の変数に代入すると、所有権はコピーされずにムーブされます。
所有権の移動を確認する
s1の値をs2に代入すると何が起きるか確認しましょう。コードを実行してみてください。
fn main() {
let s1 = String::from("Hello, CoddyKit!");
let s2 = s1; // Ownership of the String data moves from s1 to s2
// println!("{}", s1); // This line would cause a compile-time error!
println!("{}", s2);
}「ムーブ」セマンティクスを理解する
let s2 = s1;の後、s1は有効な値として扱われなくなります。Rustは、s1を再び使用することを防ぎます。
- これはムーブと呼ばれます。スタック上のポインター、長さ、容量はコピーされますが、ヒープ上のデータ自体はコピーされません。
- もし
s1が有効なままだと、スコープを外れたときにs1とs2の両方が同じメモリを解放しようとします(二重解放エラー)。
Rustの所有権システムは、これをコンパイル時に防ぎます。
所有権と関数呼び出し
値を関数に渡す処理は、別の変数に代入する処理と同様に動作します。所有権が関数にムーブされます。
関数が終了すると、値の所有者である関数パラメーターがスコープを外れ、その値は破棄されます。
関数への所有権移動を確認する
String値がtakes_ownershipにムーブされ、その後gives_ownershipが新しいStringを返す様子を確認しましょう。
fn takes_ownership(some_string: String) {
println!("Inside takes_ownership: {}", some_string);
} // some_string goes out of scope and `drop` is called.
fn gives_ownership() -> String {
let some_string = String::from("returned string");
some_string // Ownership is moved out of the function
}
fn main() {
let s1 = String::from("hello");
takes_ownership(s1); // s1's value moves into takes_ownership
// println!("{}", s1); // Error: s1 is no longer valid here!
let s2 = gives_ownership(); // s2 gets ownership of the returned String
println!("After gives_ownership: {}", s2);
}ルール3:スコープと破棄
最後のルールは次のとおりです。所有者がスコープを外れると、その値は破棄されます。
- スコープとは、プログラム内で項目が有効である範囲のことで、通常は
{}の中括弧で定義されます。 - 変数がスコープを外れると、Rustは
dropという特別な関数を自動的に呼び出します。
これにより、ガベージコレクターなしでメモリが自動的かつ安全に解放されます。
メモリエラーを防ぐ
所有権の規則は連携して、メモリ安全性を保証します。
- 所有者は1つ:コードの複数の部分が同じメモリを解放しようとするのを防ぎます。
- スコープ終了時に破棄:メモリが正確に1回、適切なタイミングで解放されることを保証します。
これにより、二重解放エラーや解放済みメモリの使用など、よくあるバグをコンパイル時に排除できます。
所有権の確認
次のRustコードについて考えてみましょう。コンパイルして実行すると、どうなるでしょうか。
fn main() {
let message = String::from("Rust is fun!");
let greeting = message;
println!("{}", message);
}復習:所有権の基本
よくできました。Rustの所有権システムの基本的なルールを学びました。
- すべての値には所有者がいます。
- 同時に存在できる所有者は1つだけです。
- 所有者がスコープを外れると、値は破棄されます。
このシステムにより、ガベージコレクターなしでよくあるメモリエラーを防げます。次は、所有権を移動せずにデータを共有する借用について学びます。
よくある質問
「Rustの所有権モデルを理解する」レッスンは無料ですか?
はい。「Rustの所有権モデルを理解する」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Learn Rust Codingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Learn Rust Codingコースには全3レッスンが含まれています。
「Rustの所有権モデルを理解する」で何を学びますか?
所有権の基本ルールとムーブセマンティクスを理解し、double-freeのような一般的なメモリエラーを防ぐ仕組みを学びます。 ブラウザで直接実行するハンズオンコードでLearn Rust Codingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
Learn Rust Codingを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのLearn Rust Codingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/3です。
「Rustの所有権モデルを理解する」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このLearn Rust Codingレッスンでコードを書いて実行できますか?
はい。すべてのLearn Rust Codingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Rustの所有権モデルを理解する
- 参照と借用を理解する
- 安全な参照のためのライフタイム